﻿using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Xml;
using System.Windows.Input;
using System;
using SHomeWorkshop.LunarConcept.Controls;
using SHomeWorkshop.LunarConcept.Adorners;
using SHomeWorkshop.LunarConcept.Tools;
using SHomeWorkshop.LunarConcept.ModifingManager;
using SHomeWorkshop.LunarConcept.Enums;
using SHomeWorkshop.LunarConcept.Widgets.Interfaces;
using System.Collections.Generic;

namespace SHomeWorkshop.LunarConcept.Widgets
{
    /// <summary>
    /// 创建时间：2012年1月18日
    /// 创建者：  杨震宇
    /// 
    /// 主要用途：折线部件。
    /// </summary>
    public class PolyLineWidget : ArrowLineWidget, Interfaces.ICanSameSize, Interfaces.ILinkableLine
    {
        #region 构造方法=====================================================================================================

        /// <summary>
        /// [静态构造方法]
        /// </summary>
        static PolyLineWidget()
        {
            dashArray = new DoubleCollection() { 2, 2 };
            contextMenu = (ContextMenu)Globals.MainWindow.MainGrid.FindResource("CMDicPolyLineWidget");
        }

        /// <summary>
        /// [构造方法]
        /// </summary>
        public PolyLineWidget(PageEditor masterEditor)
            : base(masterEditor)
        {
            this.ContextMenu = contextMenu;

            widgetType = Enums.WidgetTypes.PolyLine;
            widgetClassLocalName = Widget.GetWidgetClassLocalName(this.GetType().Name);

            mainPath.Data = new PathGeometry();
            mainPathFigure = new PathFigure() { IsClosed = false };
            (mainPath.Data as PathGeometry).Figures.Add(mainPathFigure);
            mainPathFigure.Segments.Add(mainPolySegment);

            mainPath.Fill = null;
            mainPath.Stroke = WidgetForeColor;

            mainPath.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(mainPath_PreviewMouseLeftButtonDown);
            mainPath.PreviewMouseRightButtonUp += new MouseButtonEventHandler(mainPath_PreviewMouseRightButtonUp);

            this.mainCanvas.Children.Add(mainPath);

            Canvas.SetZIndex(mainPath, 0);

            #region 两个箭头。
            //startArrowPath.Cursor = Cursors.Arrow;
            startArrowPath.Fill = startArrowPath.Stroke = WidgetForeColor;
            startArrowPath.StrokeThickness = widgetLineWidth;
            PathGeometry startArrowPg = new PathGeometry();
            startArrowPath.Data = startArrowPg;

            startArrowPathFigure.IsClosed = true;
            startArrowPathFigure.IsFilled = true;
            startArrowPathFigure.Segments.Add(startArrowPolyLineSegment);

            startArrowPg.Figures.Add(startArrowPathFigure);

            //endArrowPath.Cursor = Cursors.Arrow;
            endArrowPath.Fill = endArrowPath.Stroke = WidgetForeColor;
            endArrowPath.StrokeThickness = widgetLineWidth;
            PathGeometry endArrowPg = new PathGeometry();
            endArrowPath.Data = endArrowPg;

            endArrowPathFigure.IsClosed = true;
            endArrowPathFigure.IsFilled = true;
            endArrowPathFigure.Segments.Add(endArrowPolyLineSegment);

            endArrowPg.Figures.Add(endArrowPathFigure);

            mainCanvas.Children.Add(startArrowPath);
            mainCanvas.Children.Add(endArrowPath);

            Canvas.SetZIndex(startArrowPath, 1);
            Canvas.SetZIndex(endArrowPath, 1);
            #endregion

            centerCPCtrl = new LineCtrlAdorner(this.mainPath, this, Brushes.Yellow) { Visibility = Visibility.Hidden };
            startCtrl = new LineCtrlAdorner(this.mainPath, this, Brushes.Red) { Visibility = Visibility.Hidden };
            endCtrl = new LineCtrlAdorner(this.mainPath, this, Brushes.Blue) { Visibility = Visibility.Hidden };
            startPresentateAdorner = new WidgetPresentateAdorner(this.mainPath, this, Brushes.Red) { Visibility = Visibility.Hidden };
            startPresentateAdorner.PreviewMouseLeftButtonDown += PresentateAdorner_PreviewMouseLeftButtonDown;
            endPresentateAdorner = new WidgetPresentateAdorner(this.mainPath, this, Brushes.Blue) { Visibility = Visibility.Hidden };
            endPresentateAdorner.PreviewMouseLeftButtonDown += PresentateAdorner_PreviewMouseLeftButtonDown;

            this.commentAdorner = new CommentAdorner(this.mainPath, this) { Visibility = System.Windows.Visibility.Collapsed };//默认不显示。
            this.commentAdorner.MouseLeftButtonUp += new MouseButtonEventHandler(commentAdorner_MouseLeftButtonUp);

            this.hyperLinkAdorner = new HyperLinkAdorner(this.mainPath, this) { Visibility = Visibility.Collapsed };
            this.hyperLinkAdorner.MouseLeftButtonUp += new MouseButtonEventHandler(hyperLinkAdorner_MouseLeftButtonUp);

            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this.mainCanvas);
            if (adornerLayer == null)
            {
                MessageBox.Show("　　未找到Widget的装饰层！", Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
            }
            else
            {
                adornerLayer.Add(this.centerCPCtrl);
                adornerLayer.Add(this.startCtrl);
                adornerLayer.Add(this.endCtrl);
                adornerLayer.Add(this.startPresentateAdorner);
                adornerLayer.Add(this.endPresentateAdorner);
                adornerLayer.Add(this.commentAdorner);//这个要在各具体部件类中添加。
                adornerLayer.Add(this.hyperLinkAdorner);//这个要在各具体部件类中添加。
            }

            centerCPCtrl.MouseLeftButtonDown += new MouseButtonEventHandler(centerCPCtrl_MouseLeftButtonDown);

            startCtrl.MouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(startCtrl_MouseLeftButtonDown);
            endCtrl.MouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(endCtrl_MouseLeftButtonDown);

            startCtrl.ToolTip = endCtrl.ToolTip = CenterCPCtrl.ToolTip = "双击鼠标左键设置备注文本";

            startArrowPath.MouseLeftButtonDown += new MouseButtonEventHandler(startArrowPath_MouseLeftButtonDown);
            endArrowPath.MouseLeftButtonDown += new MouseButtonEventHandler(endArrowPath_MouseLeftButtonDown);

            //最后添加文本面板。//已移动到基类中。2013年3月13日
            //this.mainCanvas.Children.Add(this.mainTextPanel);
            //Canvas.SetZIndex(this.mainTextPanel, 2);

            this.ControlHandlerDoubleClicked += PolyLineWidget_ControlHandlerDoubleClicked;
        }

        private bool isPresentating = false;
        /// <summary>
        /// 是否处于演示状态。
        /// </summary>
        public bool IsPresentating
        {
            get { return isPresentating; }
            set
            {
                isPresentating = value;
                RefreshWidgetLineColor();
            }
        }

        private void PresentateAdorner_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            IsPresentating = !IsPresentating;
            this.IsSelected = false;
            e.Handled = true;
        }

        private void PolyLineWidget_ControlHandlerDoubleClicked(object sender, MouseButtonEventArgs e)
        {
            LunarMessage.Warning(Commands.SetCommentTextCommand.Execute());
        }

        #endregion


        #region 字段与属性===================================================================================================

        public override Point BottomRight
        {
            get
            {
                double minLeft, minTop, maxRight, maxBottom;

                minLeft = Math.Min(Math.Min(startPoint.X, endPoint.X), centerCPPoint.X);
                maxRight = Math.Max(Math.Max(startPoint.X, endPoint.X), centerCPPoint.X);

                minTop = Math.Min(Math.Min(startPoint.Y, endPoint.Y), centerCPPoint.Y);
                maxBottom = Math.Max(Math.Max(startPoint.Y, endPoint.Y), centerCPPoint.Y);

                return new Point(maxRight, maxBottom);
            }
        }

        private Point centerBasePoint;

        private LineCtrlAdorner centerCPCtrl;
        /// <summary>
        /// [只读]中控制点（装饰器）。——CP指ControlPoint。
        /// </summary>
        public LineCtrlAdorner CenterCPCtrl
        {
            get { return centerCPCtrl; }
        }

        private Point centerCPPoint = new Point();
        [Tools.LunarProperty("CenterCPPoint", PropertyDateType.Point)]
        public Point CenterCPPoint
        {
            get { return centerCPPoint; }
            set
            {
                centerCPPoint = FormatPoint(value);

                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.CenterCPPointTag, centerCPPoint.ToString());
                }

                RefreshLocation();
            }
        }

        /// <summary>
        /// 本类通用上下文菜单。
        /// </summary>
        private static ContextMenu contextMenu;

        private Orientation direction = Orientation.Vertical;
        /// <summary>
        /// 指出三折线中间一段是水平方向还是垂直向。
        /// </summary>
        [Tools.LunarProperty("Direction", PropertyDateType.Orientation)]
        public Orientation Direction
        {
            get { return direction; }
            set
            {
                direction = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.DirectionTag, value.ToString());
                }
                RefreshLocation();
            }
        }

        private ControlDraggingType draggingType = ControlDraggingType.None;
        /// <summary>
        /// [只读]正在拖动哪个控制点。
        /// </summary>
        public ControlDraggingType DraggingType
        {
            get { return draggingType; }
        }

        private Point endBasePoint;

        private LineCtrlAdorner endCtrl;
        /// <summary>
        /// [只读]尾控制点（装饰器）。
        /// </summary>
        public LineCtrlAdorner EndCtrl
        {
            get { return endCtrl; }
        }

        private Point endPoint = new Point();
        /// <summary>
        /// [读写]线的终点坐标。
        /// </summary>
        [Tools.LunarProperty("EndPoint", PropertyDateType.Point)]
        public Point EndPoint
        {
            get { return endPoint; }
            set
            {
                endPoint = FormatPoint(value);

                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.EndPointTag, endPoint.ToString());
                }

                RefreshLocation();
            }
        }

        /// <summary>
        /// 演示时才显示的，用以启动动画来画线。
        /// </summary>
        private WidgetPresentateAdorner startPresentateAdorner;

        /// <summary>
        /// 演示时才显示的，用以启动动画来画线。
        /// </summary>
        public WidgetPresentateAdorner StartPresentateAdorner { get { return startPresentateAdorner; } }

        /// <summary>
        /// 演示时才显示的，用以启动动画来画线。
        /// </summary>
        private WidgetPresentateAdorner endPresentateAdorner;

        /// <summary>
        /// 演示时才显示的，用以启动动画来画线。
        /// </summary>
        public WidgetPresentateAdorner EndPresentateAdorner { get { return endPresentateAdorner; } }

        private PolyLineForms lineForm = PolyLineForms.PolyLine;
        /// <summary>
        /// [读写]画成思维导图线。此属性总是可以设置的，
        /// 但必须在作为连接线时才起作用（以IsLinked为前提）。
        /// </summary>
        [Tools.LunarProperty("LineForm", PropertyDateType.PolyLineForm)]
        public PolyLineForms LineForm
        {
            get { return lineForm; }
            set
            {
                lineForm = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.LineFormTag, value.ToString());
                }

                this.RefreshLineForm();
            }
        }

        /// <summary>
        /// [只读]是否被挂接到两个ContentWidget。
        /// </summary>
        public bool IsLinked
        {
            get
            {
                if (startMasterId == string.Empty && endMasterId == string.Empty)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
        }

        /// <summary>
        /// 连接线永不被设置为锁定。
        /// </summary>
        [Tools.LunarProperty("IsLocked", PropertyDateType.Bool)]
        public override bool IsLocked
        {
            get
            {
                if (IsLinked) return false;

                return base.IsLocked;
            }
            set
            {
                if (IsLinked) return;//连接线不被设置为锁定。

                base.IsLocked = value;
            }
        }

        public override bool IsSelected
        {
            get { return base.IsSelected; }
            set
            {
                base.IsSelected = value;

                //显示控制点。
                if (isSelected)
                {
                    startCtrl.Visibility = centerCPCtrl.Visibility =
                        endCtrl.Visibility = Visibility.Visible;
                }
                else
                {
                    startCtrl.Visibility = centerCPCtrl.Visibility =
                        endCtrl.Visibility = Visibility.Hidden;
                }
            }
        }

        private bool isTextAtLeftOrTop = true;
        /// <summary>
        /// [读写]文本区是否位于左侧或顶侧。若为false则位于右侧或底侧。默认为true。
        /// </summary>
        [LunarProperty("IsTextAtLeftOrTop", PropertyDateType.Bool)]
        public bool IsTextAtLeftOrTop
        {
            get { return isTextAtLeftOrTop; }
            set
            {
                isTextAtLeftOrTop = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.IsTextAtLeftOrTopTag, value.ToString());
                }
                this.RefreshTextPanelLocatin();
            }
        }

        private Path mainPath = new Path() { Cursor = Cursors.Hand };

        public Path MainPath
        {
            get { return mainPath; }
        }

        private PathFigure mainPathFigure;

        public PathFigure MainPathFigure
        {
            get { return mainPathFigure; }
        }

        private PolyLineSegment mainPolySegment = new PolyLineSegment();

        private LineCtrlAdorner startCtrl;

        public LineCtrlAdorner StartCtrl
        {
            get { return startCtrl; }
        }

        private Point startBasePoint;

        private Point startPoint = new Point(0, 0);
        /// <summary>
        /// [读写]线的起点坐标。
        /// </summary>
        [Tools.LunarProperty("StartPoint", PropertyDateType.Point)]
        public Point StartPoint
        {
            get { return startPoint; }
            set
            {
                startPoint = FormatPoint(value);

                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.StartPointTag, startPoint.ToString());
                }

                RefreshLocation();
            }
        }


        private string startMasterId = string.Empty;
        /// <summary>
        /// [读写]首端点挂接的部件的Id。
        /// </summary>
        [Tools.LunarProperty("StartMasterId", PropertyDateType.String)]
        public string StartMasterId
        {
            get { return startMasterId; }
            set
            {
                startMasterId = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.StartMasterIdTag, value);
                }
            }
        }

        private string endMasterId = string.Empty;
        /// <summary>
        /// [读写]尾端点挂接到的部件的Id。
        /// </summary>
        [Tools.LunarProperty("EndMasterId", PropertyDateType.String)]
        public string EndMasterId
        {
            get { return endMasterId; }
            set
            {
                endMasterId = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.EndMasterIdTag, value);
                }
            }
        }

        public override Point TopLeft
        {
            get
            {
                double minLeft, minTop, maxRight, maxBottom;

                minLeft = Math.Min(Math.Min(startPoint.X, endPoint.X), centerCPPoint.X);
                maxRight = Math.Max(Math.Max(startPoint.X, endPoint.X), centerCPPoint.X);

                minTop = Math.Min(Math.Min(startPoint.Y, endPoint.Y), centerCPPoint.Y);
                maxBottom = Math.Max(Math.Max(startPoint.Y, endPoint.Y), centerCPPoint.Y);

                return new Point(minLeft, minTop);
            }
        }

        #endregion


        #region 方法=========================================================================================================

        public override void Build()
        {
            base.Build();

            if (this.xmlData == null) return;

            XmlAttribute attrStartMasterId = this.xmlData.GetAttribute(XmlTags.StartMasterIdTag);
            if (attrStartMasterId != null)
            {
                this.startMasterId = attrStartMasterId.Value;
            }

            XmlAttribute attrEndMasterId = this.xmlData.GetAttribute(XmlTags.EndMasterIdTag);
            if (attrEndMasterId != null)
            {
                this.endMasterId = attrEndMasterId.Value;
            }

            XmlAttribute attrStartPoint = this.xmlData.GetAttribute(XmlTags.StartPointTag);
            if (attrStartPoint != null)
            {
                this.startPoint = FormatPoint(Point.Parse(attrStartPoint.Value));
            }

            XmlAttribute attrCenterCPPoint = this.xmlData.GetAttribute(XmlTags.CenterCPPointTag);
            if (attrCenterCPPoint != null)
            {
                this.centerBasePoint = this.centerCPPoint = FormatPoint(Point.Parse(attrCenterCPPoint.Value));
            }

            XmlAttribute attrEndPoint = this.xmlData.GetAttribute(XmlTags.EndPointTag);
            if (attrEndPoint != null)
            {
                this.endPoint = FormatPoint(Point.Parse(attrEndPoint.Value));
            }

            XmlAttribute attrDirection = this.xmlData.GetAttribute(XmlTags.DirectionTag);
            if (attrDirection != null)
            {
                this.direction = (Orientation)Enum.Parse(typeof(Orientation), attrDirection.Value);
            }

            XmlAttribute attrIsTextAtLeftOrTop = this.xmlData.GetAttribute(XmlTags.IsTextAtLeftOrTopTag);
            if (attrIsTextAtLeftOrTop != null)
            {
                this.isTextAtLeftOrTop = bool.Parse(attrIsTextAtLeftOrTop.Value);
            }

            XmlAttribute attrLineForm = this.xmlData.GetAttribute(XmlTags.LineFormTag);
            if (attrLineForm != null)
            {
                this.lineForm = (Enums.PolyLineForms)Enum.Parse(typeof(Enums.PolyLineForms), attrLineForm.Value);
            }

            //包含RefreshArrows()调用。
            this.RefreshLocation();

            //此类是下面这几个属性的“最终实现类”。这些属性的值都已在基类确定。因此调用,
            this.RefreshWidgetLineColor();
            this.RefreshWidgetLineWidth();
            this.RefreshLineDash();

        }

        protected override void BuildStyleProperties()
        {
            base.BuildStyleProperties();

            //没有必须在此类读取的、与Style相关的Xml特性
        }

        public override void BuildWidgetStylePropertiesAndRefresh()
        {
            base.BuildWidgetStylePropertiesAndRefresh();

            //此类是下面这几个属性的“最终实现类”。这些属性的值都已在基类确定。因此调用,
            this.RefreshWidgetLineColor();
            this.RefreshWidgetLineWidth();
            this.RefreshLineDash();

            //已在ArrowLineWidget类中调用。
            //this.RefreshWidgetBackColor();
            //this.RefreshArrows();

            //无意义
            //this.RefreshWidgetPadding();

            //这几个在Widget类中已经调用。
            //this.RefreshWidgetForeColor();
            //this.RefreshIsShadowVisible();
            //this.RefreshWidgetOpacity();
        }

        void centerCPCtrl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ClickCount == 2)
            {
                OnControlHandlerDoubleClicked(sender, e);
                e.Handled = true;
                return;
            }

            this.SelectOnlySelf();

            //开始拖动。
            e.Handled = true;
            masterEditor.MouseInfo.LeftButtonPreviewPoint = centerCPPoint;
            draggingType = ControlDraggingType.CenterCP;
            masterEditor.MouseInfo.DraggingType = PageDraggingType.MoveLineWidgetControler;

            centerCPCtrl.Visibility = System.Windows.Visibility.Hidden;
        }

        /// <summary>
        /// 根据“IsLinked”的结果分别重绘线条。
        /// </summary>
        public void DrawLine()
        {
            if (masterEditor == null) return;
            if (IsLinked)
            {
                var groupId = ParentGroupId;
                if (string.IsNullOrWhiteSpace(groupId))
                {

                    Widget startWidget = masterEditor.GetWidget(this.StartMasterId);
                    Widget endWidget = masterEditor.GetWidget(this.EndMasterId);
                    if (startWidget == null || endWidget == null)
                    {
                        DrawLine(this.startPoint, this.centerCPPoint, this.endPoint);
                        return;
                    }

                    Rect startRect = startWidget.OuterRect;
                    Rect endRect = endWidget.OuterRect;
                    DrawLine(startRect, endRect);//只有被链接的才会调用。链接时centerCPPoint无意义。
                }
                else
                {
                    var groupWidget = masterEditor.GetWidget(groupId) as GroupWidget;
                    if (groupWidget != null)
                    {
                        Widget startWidget = groupWidget.GetWidget(this.StartMasterId);
                        Widget endWidget = groupWidget.GetWidget(this.EndMasterId);
                        if (startWidget == null || endWidget == null)
                        {
                            DrawLine(this.startPoint, this.centerCPPoint, this.endPoint);
                            return;
                        }

                        Rect startRect = startWidget.OuterRect;
                        Rect endRect = endWidget.OuterRect;
                        DrawLine(startRect, endRect);//只有被链接的才会调用。链接时centerCPPoint无意义。
                    }
                    else
                    {
                        DrawLine(this.startPoint, this.centerCPPoint, this.endPoint);
                        return;
                    }
                }
            }
            else
            {
                DrawLine(this.startPoint, this.centerCPPoint, this.endPoint);
            }
        }

        /// <summary>
        /// “IsLinked”为false时，表示此线未连接到ICanLinkedWidget部件。
        /// </summary>
        /// <param name="startPoint">首端点。</param>
        /// <param name="startCPPoint">中段线控制点。</param>
        /// <param name="endPoint">尾端点。</param>
        private void DrawLine(Point startPoint, Point centerCPPoint, Point endPoint)
        {
            switch (direction)
            {
                case Orientation.Vertical:
                    {
                        startBasePoint = new Point(centerCPPoint.X, startPoint.Y);
                        endBasePoint = new Point(centerCPPoint.X, endPoint.Y);
                        centerBasePoint = new Point(centerCPPoint.X,
                            startBasePoint.Y + (endBasePoint.Y - startBasePoint.Y) / 2);
                        break;
                    }
                default://水平
                    {
                        startBasePoint = new Point(startPoint.X, centerCPPoint.Y);
                        endBasePoint = new Point(endPoint.X, centerCPPoint.Y);
                        centerBasePoint = new Point(startBasePoint.X + (endBasePoint.X - startBasePoint.X) / 2,
                            centerCPPoint.Y);
                        break;
                    }
            }

            if (arrows == ArrowType.None)
            {
                mainPathFigure.StartPoint = startPoint;
                mainPolySegment.Points = new PointCollection()
                {
                    startBasePoint,endBasePoint,endPoint,
                };
            }
            else
            {
                #region 旧版
                //if (arrows == ArrowType.All || arrows == ArrowType.Start)
                //{
                //    startArrowPathFigure.StartPoint = startPoint;
                //    Tools.ArrowPoints apStart = new Tools.ArrowPoints(
                //        startArrowPathFigure.StartPoint, startBasePoint, widgetLineWidth * 2);

                //    startArrowPolyLineSegment.Points = new PointCollection(){
                //        apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
                //    };
                //    mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;
                //}
                //else
                //{
                //    mainPathFigure.StartPoint = startPoint;
                //}

                //if (arrows == ArrowType.All || arrows == ArrowType.End)
                //{
                //    endArrowPathFigure.StartPoint = endPoint;
                //    Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
                //        endArrowPathFigure.StartPoint, endBasePoint, widgetLineWidth * 2);

                //    endArrowPolyLineSegment.Points = new PointCollection(){
                //        apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                //    };
                //    endPoint = apEnd.ArrowRealTopPoint;
                //}
                ////else
                ////{
                ////    endPoint = endPoint;//不变
                ////}

                //mainPolySegment.Points = new PointCollection()
                //{
                //    startBasePoint,endBasePoint,endPoint,
                //}; 
                #endregion

                //startArrowPathFigure.StartPoint = startPoint;
                Tools.ArrowPoints apStart = new Tools.ArrowPoints(
                    startPoint, startBasePoint, Globals.MainWindow.EditorManager.DefaultFontSize);

                endArrowPathFigure.StartPoint = endPoint;
                Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
                    endPoint, endBasePoint, Globals.MainWindow.EditorManager.DefaultFontSize);
                startArrowPath.Fill = endArrowPath.Fill = WidgetBackColor;

                switch (arrows)
                {
                    case ArrowType.Start:
                        startArrowPath.Fill = widgetLineColor;
                        endArrowPath.Fill = widgetLineColor;

                        startArrowPathFigure.StartPoint = startPoint;

                        startArrowPolyLineSegment.Points = new PointCollection(){
                            apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
                        };

                        mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;
                        mainPolySegment.Points = new PointCollection()
                        {
                            startBasePoint,endBasePoint,endPoint,
                        };

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = true;

                        endArrowPathFigure.StartPoint = endPoint;
                        endArrowPolyLineSegment.Points = new PointCollection(){
                        apEnd.ArrowLeftPoint, apEnd.ArrowRightPoint,
                        };
                        break;
                    case ArrowType.End:
                        startArrowPath.Fill = widgetLineColor;
                        endArrowPath.Fill = widgetLineColor;

                        startArrowPathFigure.StartPoint = startPoint;

                        mainPathFigure.StartPoint = apStart.ArrowTopPoint;
                        mainPolySegment.Points = new PointCollection()
                        {
                            startBasePoint,endBasePoint,endPoint,
                        };

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = true;

                        endArrowPathFigure.StartPoint = endPoint;

                        endArrowPolyLineSegment.Points = new PointCollection(){
                            apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                        };

                        mainPolySegment.Points = new PointCollection()
                        {
                            startBasePoint,endBasePoint,endPoint,
                        };

                        break;
                    case ArrowType.All:
                        startArrowPath.Fill = widgetLineColor;
                        endArrowPath.Fill = widgetLineColor;

                        startArrowPathFigure.StartPoint = startPoint;

                        startArrowPolyLineSegment.Points = new PointCollection(){
                            apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
                        };

                        mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;
                        mainPolySegment.Points = new PointCollection()
                        {
                            startBasePoint,endBasePoint,endPoint,
                        };

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = true;

                        endArrowPathFigure.StartPoint = endPoint;

                        endArrowPolyLineSegment.Points = new PointCollection(){
                            apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                        };

                        mainPolySegment.Points = new PointCollection()
                        {
                            startBasePoint,endBasePoint,endPoint,
                        };

                        break;
                    case ArrowType.None:
                        startArrowPath.Fill = widgetLineColor;
                        endArrowPath.Fill = widgetLineColor;

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = true;

                        mainPathFigure.StartPoint = startPoint;
                        mainPolySegment.Points = new PointCollection()
                        {
                            startBasePoint,endBasePoint,endPoint,
                        };

                        endArrowPathFigure.StartPoint = endPoint;
                        break;
                    case ArrowType.EmptyStart:
                        startArrowPath.Fill = Brushes.Transparent; ;
                        endArrowPath.Fill = widgetBackColor;

                        mainPathFigure.StartPoint = apStart.ArrowCenter;
                        mainPolySegment.Points = new PointCollection()
                        {
                            startBasePoint,endBasePoint,endPoint,
                        };

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = true;

                        startArrowPathFigure.StartPoint = startPoint;
                        startArrowPolyLineSegment.Points = new PointCollection(){
                            apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
                        };

                        break;
                    case ArrowType.RhombStart:
                        startArrowPath.Fill = WidgetLineColor;
                        endArrowPath.Fill = WidgetLineColor;

                        mainPathFigure.StartPoint = apStart.ArrowBottom;
                        mainPolySegment.Points = new PointCollection()
                        {
                            startBasePoint,endBasePoint,endPoint,
                        };

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = true;

                        startArrowPathFigure.StartPoint = startPoint;
                        startArrowPolyLineSegment.Points = new PointCollection(){
                            apStart.ArrowLeftPoint,apStart.ArrowBottom,apStart.ArrowRightPoint,
                        };

                        break;
                    case ArrowType.EmptyRhombStart:
                        startArrowPath.Fill = Brushes.Transparent;
                        endArrowPath.Fill = widgetBackColor;

                        mainPathFigure.StartPoint = apStart.ArrowBottom;
                        mainPolySegment.Points = new PointCollection()
                        {
                            startBasePoint,endBasePoint,endPoint,
                        };

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = true;

                        startArrowPathFigure.StartPoint = startPoint;
                        startArrowPolyLineSegment.Points = new PointCollection(){
                            apStart.ArrowLeftPoint,apStart.ArrowBottom,apStart.ArrowRightPoint,
                        };

                        break;
                    case ArrowType.OpenArrowEnd:
                        startArrowPath.Fill = widgetLineColor;
                        endArrowPath.Fill = Brushes.Transparent;

                        startArrowPathFigure.StartPoint = startPoint;
                        endArrowPath.StrokeThickness = widgetLineWidth;

                        mainPathFigure.StartPoint = apStart.ArrowTopPoint;
                        mainPolySegment.Points = new PointCollection()
                        {
                            startBasePoint,endBasePoint,endPoint,
                        };

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = false;

                        endArrowPathFigure.StartPoint = apEnd.ArrowLeftPoint;
                        endArrowPolyLineSegment.Points = new PointCollection(){
                            apEnd.ArrowTopPoint,apEnd.ArrowRightPoint,
                        };

                        break;
                    case ArrowType.Arrow:
                        startArrowPath.Fill = WidgetLineColor;
                        endArrowPath.Fill = WidgetLineColor;

                        mainPathFigure.StartPoint = apStart.ArrowBottom;
                        mainPolySegment.Points = new PointCollection()
                        {
                            startBasePoint,endBasePoint,endPoint,
                        };

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = true;

                        startArrowPathFigure.StartPoint = apStart.ArrowRealTopPoint;
                        startArrowPolyLineSegment.Points = new PointCollection(){
                            apStart.ArrowRightTop,apStart.ArrowRightPoint,apStart.ArrowBottom,apStart.ArrowLeftPoint,apStart.ArrowLeftTop,
                        };

                        endArrowPathFigure.StartPoint = endPoint;
                        endArrowPolyLineSegment.Points = new PointCollection(){
                            apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                        };

                        break;
                    case ArrowType.EmptyArrow:
                        startArrowPath.Fill = Brushes.Transparent;
                        endArrowPath.Fill = Brushes.Transparent;

                        mainPathFigure.StartPoint = apStart.ArrowBottom;
                        mainPolySegment.Points = new PointCollection()
                        {
                            startBasePoint,endBasePoint,apEnd.ArrowCenter,
                        };

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = true;

                        startArrowPathFigure.StartPoint = apStart.ArrowRealTopPoint;
                        startArrowPolyLineSegment.Points = new PointCollection(){
                            apStart.ArrowRightTop,apStart.ArrowRightPoint,apStart.ArrowBottom,apStart.ArrowLeftPoint,apStart.ArrowLeftTop,
                        };

                        endArrowPathFigure.StartPoint = endPoint;
                        endArrowPolyLineSegment.Points = new PointCollection(){
                            apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
                        };

                        break;
                    default:
                        break;
                }

            }

            if (isSelected)
            {
                startCtrl.Visibility = centerCPCtrl.Visibility = endCtrl.Visibility = Visibility.Visible;
            }
            else
            {
                startCtrl.Visibility = centerCPCtrl.Visibility = endCtrl.Visibility = Visibility.Collapsed;
            }

            startCtrl.CenterPoint = startPoint;
            centerCPCtrl.CenterPoint = centerBasePoint;
            endCtrl.CenterPoint = endPoint;

            //刷新文本块位置
            LocateTextPanel(startBasePoint, endBasePoint, this.direction);
        }

        /// <summary>
        /// ★此方法不会调用DrawLine(Point,Point,Point,Point)方法来进行绘制（会重复计算坐标点，效率较低）。
        /// ★应保持此方法与重载版本行为一致！！！
        /// 
        /// “IsLinked”属性为true时，曲线被连接到两个ICanLinkedWidget部件。
        /// 此时，曲线的位置和形状由这两个部件的外框和曲线的两个控制点决定。
        /// 曲线的首端点、尾端点将自动计算，计算的规则是：“首控制点到首矩形的中心点与矩形的交战为首端点”。
        /// </summary>
        /// <param name="startRect">首连接部件外框。</param>
        /// <param name="endRect">尾连接部件外框。</param>
        private void DrawLine(Rect startRect, Rect endRect)
        {
            startRect.X -= 4; startRect.Y -= 4; startRect.Width += 8; startRect.Height += 8;
            endRect.X -= 4; endRect.Y -= 4; endRect.Width += 8; endRect.Height += 8;

            if (startRect.IntersectsWith(endRect))
            {
                startArrowPath.Visibility = endArrowPath.Visibility =
                mainPath.Visibility = Visibility.Hidden;
            }
            else
            {
                mainPath.Visibility = Visibility.Visible;

                //看看能否按FishBone方式或C形线（匚形线）方式来绘制
                //如果可以，就按FishBone来绘制，否则继续
                switch (lineForm)
                {
                    case PolyLineForms.BigFishBone:
                        {
                            //如果空间不够绘制鱼骨图中骨，则按普通折线绘制
                            if (DrawBigFishBone(startRect, endRect)) return;
                            else break;
                        }
                    case PolyLineForms.MediumFishBone:
                        {
                            //如果空间不够绘制鱼骨图中骨，则按普通折线绘制
                            if (DrawMediumFishBone(startRect, endRect)) return;
                            else break;
                        }
                    case PolyLineForms.CLine:
                        {
                            if (DrawCLine(startRect, endRect)) return;
                            else break;
                        }
                    case PolyLineForms.LLine:
                        {
                            if (DrawLLine(startRect, endRect)) return;
                            else break;
                        }
                    //case PolyLineForms.PolyLine: break;//直接继续绘制
                    default: break;
                }

                switch (arrows)
                {
                    case ArrowType.All:
                        {
                            startArrowPath.Visibility = endArrowPath.Visibility = Visibility.Visible; break;
                        }
                    case ArrowType.End:
                        {
                            startArrowPath.Visibility = Visibility.Hidden;
                            endArrowPath.Visibility = Visibility.Visible;
                            break;
                        }
                    case ArrowType.Start:
                        {
                            startArrowPath.Visibility = Visibility.Visible;
                            endArrowPath.Visibility = Visibility.Hidden;
                            break;
                        }
                    case ArrowType.None:
                        {
                            startArrowPath.Visibility = endArrowPath.Visibility = Visibility.Hidden; break;
                        }
                }

                mainPath.Visibility = Visibility.Visible;
            }

            Point startCenter = new Point(startRect.Left + startRect.Width / 2,
                startRect.Top + startRect.Height / 2);
            Point endCenter = new Point(endRect.Left + endRect.Width / 2,
                endRect.Top + endRect.Height / 2);

            Tools.PointToRect.ArrowPoints aptStart = Tools.PointToRect.GetCrossPointToRect(startRect, startBasePoint);
            Tools.PointToRect.ArrowPoints aptEnd = Tools.PointToRect.GetCrossPointToRect(endRect, endBasePoint);

            Point tmpStartPt;
            Point tmpEndPt;

            //两个矩形不相交，又分这样几种情况：
            //１.如果两个矩形之间水平方向上有部分重叠；——此时折线中段只能纵向。取左、右边中点。
            //２.如果两个矩形之间垂直方向上有部分重叠；——此时折线中段只能横向。取顶、底边中点。
            //３.如果两个矩形之间没有任何重叠；此时由折线自身决定中段线的方向。据此决定取哪两个边的中点。

            if ((startRect.Bottom >= endRect.Top && startRect.Bottom <= endRect.Bottom) ||
                (startRect.Top >= endRect.Top && startRect.Top <= endRect.Bottom) ||
                (endRect.Bottom >= startRect.Top && endRect.Bottom <= startRect.Bottom) ||
                (endRect.Top >= startRect.Top && endRect.Top <= startRect.Bottom))
            {
                //水平方向上至少有部分重叠：
                if (aptStart.Top.X < startCenter.X)
                {
                    tmpStartPt = new Point(startRect.Left - 2, startCenter.Y);
                }
                else
                {
                    tmpStartPt = new Point(startRect.Right + 2, startCenter.Y);
                }

                if (aptEnd.Top.X < endCenter.X)
                {
                    tmpEndPt = new Point(endRect.Left - 2, endCenter.Y);
                }
                else
                {
                    tmpEndPt = new Point(endRect.Right + 2, endCenter.Y);
                }

                this.startPoint =
                mainPathFigure.StartPoint = FormatPoint(tmpStartPt);
                startBasePoint = FormatPoint(new Point(tmpStartPt.X + (tmpEndPt.X - tmpStartPt.X) / 2, tmpStartPt.Y));
                endBasePoint = FormatPoint(new Point(startBasePoint.X, tmpEndPt.Y));

                tmpEndPt = FormatPoint(tmpEndPt);

                mainPolySegment.Points = new PointCollection()
                {
                    startBasePoint,endBasePoint,tmpEndPt,
                };

                this.centerBasePoint = new Point(startBasePoint.X + (endBasePoint.X - startBasePoint.X) / 2,
                    startBasePoint.Y + (endBasePoint.Y - startBasePoint.Y) / 2);

                this.centerCPPoint = centerBasePoint;
                this.endPoint = tmpEndPt;

                LocateTextPanel(startBasePoint, endBasePoint, Orientation.Vertical);
            }
            else
            {
                if ((startRect.Left >= endRect.Left && startRect.Left <= endRect.Right) ||
                    (startRect.Right >= endRect.Left && startRect.Right <= endRect.Right) ||
                    (endRect.Left >= startRect.Left && endRect.Left <= startRect.Right) ||
                    (endRect.Right >= startRect.Left && endRect.Right <= startRect.Right))
                {
                    //垂直方向至少有部分重叠，中段线只能横向：
                    if (aptStart.Top.Y < startCenter.Y)
                    {
                        tmpStartPt = new Point(startCenter.X, startRect.Top - 2);
                    }
                    else
                    {
                        tmpStartPt = new Point(startCenter.X, startRect.Bottom + 2);
                    }

                    if (aptEnd.Top.Y < endCenter.Y)
                    {
                        tmpEndPt = new Point(endCenter.X, endRect.Top - 2);
                    }
                    else
                    {
                        tmpEndPt = new Point(endCenter.X, endRect.Bottom + 2);
                    }

                    this.startPoint =
                    mainPathFigure.StartPoint = FormatPoint(tmpStartPt);
                    startBasePoint = FormatPoint(new Point(tmpStartPt.X, tmpStartPt.Y + (tmpEndPt.Y - tmpStartPt.Y) / 2));
                    endBasePoint = FormatPoint(new Point(tmpEndPt.X, startBasePoint.Y));

                    tmpEndPt = FormatPoint(tmpEndPt);

                    mainPolySegment.Points = new PointCollection()
                    {
                        startBasePoint,endBasePoint, tmpEndPt,
                    };

                    this.centerBasePoint = new Point(startBasePoint.X + (endBasePoint.X - startBasePoint.X) / 2,
                        startBasePoint.Y + (endBasePoint.Y - startBasePoint.Y) / 2);

                    this.centerCPPoint = centerBasePoint;
                    this.endPoint = tmpEndPt;

                    LocateTextPanel(startBasePoint, endBasePoint, Orientation.Horizontal);
                }
                else
                {
                    //没有任何重叠：
                    if (direction == Orientation.Horizontal)
                    {
                        if (endCenter.Y > startCenter.Y)
                        {
                            tmpStartPt = new Point(startCenter.X, startRect.Bottom + 2);
                            tmpEndPt = new Point(endCenter.X, endRect.Top - 2);
                        }
                        else
                        {
                            tmpStartPt = new Point(startCenter.X, startRect.Top - 2);
                            tmpEndPt = new Point(endCenter.X, endRect.Bottom + 2);
                        }

                        this.startPoint =
                        mainPathFigure.StartPoint = FormatPoint(tmpStartPt);
                        startBasePoint = FormatPoint(new Point(tmpStartPt.X, tmpStartPt.Y + (tmpEndPt.Y - tmpStartPt.Y) / 2));
                        endBasePoint = FormatPoint(new Point(tmpEndPt.X, startBasePoint.Y));

                        tmpEndPt = FormatPoint(tmpEndPt);

                        mainPolySegment.Points = new PointCollection()
                        {
                            startBasePoint,endBasePoint, tmpEndPt,
                        };
                    }
                    else
                    {
                        if (endCenter.X > startCenter.X)
                        {
                            tmpStartPt = new Point(startRect.Right + 2, startCenter.Y);
                            tmpEndPt = new Point(endRect.Left - 2, endCenter.Y);
                        }
                        else
                        {
                            tmpStartPt = new Point(startRect.Left - 2, startCenter.Y);
                            tmpEndPt = new Point(endRect.Right + 2, endCenter.Y);
                        }

                        this.startPoint =
                        mainPathFigure.StartPoint = FormatPoint(tmpStartPt);
                        startBasePoint = FormatPoint(new Point(tmpStartPt.X + (tmpEndPt.X - tmpStartPt.X) / 2, tmpStartPt.Y));
                        endBasePoint = FormatPoint(new Point(startBasePoint.X, tmpEndPt.Y));

                        tmpEndPt = FormatPoint(tmpEndPt);

                        mainPolySegment.Points = new PointCollection()
                        {
                            startBasePoint,endBasePoint, tmpEndPt,
                        };
                    }

                    this.centerBasePoint = new Point(startBasePoint.X + (endBasePoint.X - startBasePoint.X) / 2,
                        startBasePoint.Y + (endBasePoint.Y - startBasePoint.Y) / 2);

                    this.centerCPPoint = centerBasePoint;
                    this.endPoint = tmpEndPt;

                    //只有这里，部件定义的中段线direction才是有效的。
                    LocateTextPanel(startBasePoint, endBasePoint, this.direction);
                }
            }

            //重新计算箭头位置。
            var apStart = new ArrowPoints(tmpStartPt, startBasePoint, Globals.MainWindow.EditorManager.DefaultFontSize);
            var apEnd = new ArrowPoints(tmpEndPt, endBasePoint, Globals.MainWindow.EditorManager.DefaultFontSize);

            switch (this.Arrows)
            {
                case ArrowType.All:
                    {
                        this.startArrowPathFigure.StartPoint = apStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apStart.ArrowLeftPoint, apStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = apEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apEnd.ArrowLeftPoint, apEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,apEnd.ArrowRealTopPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetLineColor;
                        EndArrowPath.Fill = WidgetLineColor;

                        startArrowPath.Visibility = endArrowPath.Visibility = Visibility.Visible; break;
                    }
                case ArrowType.End:
                    {
                        this.startArrowPathFigure.StartPoint = apStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apStart.ArrowLeftPoint, apStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = apEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apEnd.ArrowLeftPoint, apEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = startPoint;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetLineColor;
                        EndArrowPath.Fill = WidgetLineColor;

                        startArrowPath.Visibility = Visibility.Hidden;
                        endArrowPath.Visibility = Visibility.Visible;
                        break;
                    }
                case ArrowType.Start:
                    {
                        this.startArrowPathFigure.StartPoint = apStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apStart.ArrowLeftPoint, apStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = apEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apEnd.ArrowLeftPoint, apEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = startPoint;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetLineColor;
                        EndArrowPath.Fill = WidgetLineColor;

                        startArrowPath.Visibility = Visibility.Visible;
                        endArrowPath.Visibility = Visibility.Hidden;
                        break;
                    }
                case ArrowType.None:
                    {
                        this.startArrowPathFigure.StartPoint = apStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apStart.ArrowLeftPoint, apStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = apEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apEnd.ArrowLeftPoint, apEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = startPoint;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetLineColor;
                        EndArrowPath.Fill = WidgetLineColor;
                        startArrowPath.Visibility = endArrowPath.Visibility = Visibility.Hidden; break;
                    }
                case ArrowType.EmptyStart:
                    {
                        this.startArrowPathFigure.StartPoint = apStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apStart.ArrowLeftPoint, apStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = apEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apEnd.ArrowLeftPoint, apEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = startPoint;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = widgetBackColor;
                        EndArrowPath.Fill = WidgetLineColor;
                        startArrowPath.Visibility = Visibility.Visible;
                        endArrowPath.Visibility = Visibility.Hidden;
                        break;
                    }
                case ArrowType.RhombStart:
                    {
                        this.startArrowPathFigure.StartPoint = apStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apStart.ArrowLeftPoint, apStart.ArrowBottom, apStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = apEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apEnd.ArrowLeftPoint, apEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = apStart.ArrowBottom;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,apEnd.ArrowRealTopPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetLineColor;
                        EndArrowPath.Fill = WidgetLineColor;

                        startArrowPath.Visibility = Visibility.Visible;
                        endArrowPath.Visibility = Visibility.Hidden;
                        break;
                    }
                case ArrowType.EmptyRhombStart:
                    {
                        this.startArrowPathFigure.StartPoint = apStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apStart.ArrowLeftPoint, apStart.ArrowBottom, apStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = apEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apEnd.ArrowLeftPoint, apEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = apStart.ArrowBottom;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetBackColor;
                        EndArrowPath.Fill = WidgetLineColor;

                        startArrowPath.Visibility = Visibility.Visible;
                        endArrowPath.Visibility = Visibility.Hidden;
                        break;
                    }
                case ArrowType.Arrow:
                    {
                        this.startArrowPathFigure.StartPoint = apStart.ArrowRealTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apStart.ArrowLeftTop,apStart.ArrowLeftPoint, apStart.ArrowBottom,apStart.ArrowRightPoint,apStart.ArrowRightTop,
                        };

                        this.endArrowPathFigure.StartPoint = apEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apEnd.ArrowLeftPoint, apEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = apStart.ArrowBottom;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetLineColor;
                        EndArrowPath.Fill = WidgetLineColor;

                        startArrowPath.Visibility = Visibility.Visible;
                        endArrowPath.Visibility = Visibility.Visible;
                        break;
                    }
                case ArrowType.EmptyArrow:
                    {
                        this.startArrowPathFigure.StartPoint = apStart.ArrowRealTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apStart.ArrowLeftTop,apStart.ArrowLeftPoint, apStart.ArrowBottom,apStart.ArrowRightPoint,apStart.ArrowRightTop,
                        };

                        this.endArrowPathFigure.StartPoint = apEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apEnd.ArrowLeftPoint, apEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = apStart.ArrowBottom;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetBackColor;
                        EndArrowPath.Fill = WidgetBackColor;

                        startArrowPath.Visibility = Visibility.Visible;
                        endArrowPath.Visibility = Visibility.Visible;
                        break;
                    }
                case ArrowType.OpenArrowEnd:
                    {
                        this.startArrowPathFigure.StartPoint = apStart.ArrowRealTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apStart.ArrowLeftTop,apStart.ArrowLeftPoint, apStart.ArrowBottom,apStart.ArrowRightPoint,apStart.ArrowRightTop,
                        };

                        this.endArrowPathFigure.IsClosed = false;
                        this.endArrowPathFigure.StartPoint = apEnd.ArrowLeftPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apEnd.ArrowTopPoint, apEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = apStart.ArrowTopPoint;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,apEnd.ArrowTopPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetBackColor;
                        EndArrowPath.Fill = Brushes.Transparent;

                        startArrowPath.Visibility = Visibility.Hidden;
                        endArrowPath.Visibility = Visibility.Visible;
                        break;
                    }
            }

            //startArrowPathFigure.StartPoint = FormatPoint(tmpStartPt);
            //Tools.ArrowPoints apStart = new Tools.ArrowPoints(
            //        startArrowPathFigure.StartPoint, startBasePoint, Globals.MainWindow.EditorManager.DefaultFontSize);

            //startArrowPolyLineSegment.Points = new PointCollection()
            //{
            //    apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
            //};
            //mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;

            //endArrowPathFigure.StartPoint = FormatPoint(tmpEndPt);
            //Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
            //    endArrowPathFigure.StartPoint, endBasePoint, Globals.MainWindow.EditorManager.DefaultFontSize);
            //this.endArrowPolyLineSegment.Points = new PointCollection()
            //{
            //    apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
            //};

            //刷新控制点位置——切换指向时可能需要！
            this.startCtrl.CenterPoint = tmpStartPt;
            this.centerCPCtrl.CenterPoint = new Point(
                startBasePoint.X + (endBasePoint.X - startBasePoint.X) / 2,
                startBasePoint.Y + (endBasePoint.Y - startBasePoint.Y) / 2);

            this.endCtrl.CenterPoint = tmpEndPt;

            //刷新文本块位置不能放在此处，而需要根据中段线的自动定位状态来决定文本放置位置。
        }

        /// <summary>
        /// 绘制C形线（匚形线）。只在作连接线时有效。
        /// </summary>
        /// <param name="startRect">首挂接节点区域。</param>
        /// <param name="endRect">尾挂接节点区域。</param>
        private bool DrawCLine(Rect startRect, Rect endRect)
        {
            double padding = this.widgetLineWidth;
            endRect = new Rect(endRect.X - padding, endRect.Y - padding, endRect.Width + 2 * padding, endRect.Height + 2 * padding);

            Point startCenter = new Point(startRect.X + startRect.Width / 2, startRect.Y + startRect.Height / 2);
            Point endCenter = new Point(endRect.X + endRect.Width / 2, endRect.Y + endRect.Height / 2);

            Point startPoint;
            Point endPoint;

            var defFontSize = Globals.MainWindow.EditorManager.DefaultFontSize * 2.5;

            switch (this.Direction)
            {
                case Orientation.Horizontal:
                    {
                        if (startCenter.Y <= endCenter.Y)//中段线在顶部
                        {
                            double top = Math.Min(startRect.Top - defFontSize, endRect.Top - defFontSize);
                            startPoint = FormatPoint(new Point(startCenter.X, startRect.Top));
                            endPoint = FormatPoint(new Point(endCenter.X, endRect.Top));
                            this.startBasePoint = FormatPoint(new Point(startCenter.X, top));
                            this.endBasePoint = FormatPoint(new Point(endCenter.X, top));
                            centerBasePoint = FormatPoint(new Point(startBasePoint.X + (endBasePoint.X - startBasePoint.X) / 2, startBasePoint.Y));
                        }
                        else//中段线在底部
                        {
                            double bottom = Math.Max(startRect.Bottom + defFontSize, endRect.Bottom + defFontSize);
                            startPoint = FormatPoint(new Point(startCenter.X, startRect.Bottom));
                            endPoint = FormatPoint(new Point(endCenter.X, endRect.Bottom));
                            this.startBasePoint = FormatPoint(new Point(startCenter.X, bottom));
                            this.endBasePoint = FormatPoint(new Point(endCenter.X, bottom));
                            centerBasePoint = FormatPoint(new Point(startBasePoint.X + (endBasePoint.X - startBasePoint.X) / 2, startBasePoint.Y));
                        }
                        break;
                    }
                default:
                    {
                        if (startCenter.X <= endCenter.X)//中段线在左侧
                        {
                            double left = Math.Min(startRect.Left - defFontSize, endRect.Left - defFontSize);
                            startPoint = FormatPoint(new Point(startRect.Left, startCenter.Y));
                            endPoint = FormatPoint(new Point(endRect.Left, endCenter.Y));
                            this.startBasePoint = FormatPoint(new Point(left, startCenter.Y));
                            this.endBasePoint = FormatPoint(new Point(left, endCenter.Y));
                            centerBasePoint = FormatPoint(new Point(startBasePoint.X, startBasePoint.Y + (endBasePoint.Y - startBasePoint.Y) / 2));
                        }
                        else//中段线在右侧
                        {
                            double right = Math.Max(startRect.Right + defFontSize, endRect.Right + defFontSize);
                            startPoint = FormatPoint(new Point(startRect.Right, startCenter.Y));
                            endPoint = FormatPoint(new Point(endRect.Right, endCenter.Y));
                            this.startBasePoint = FormatPoint(new Point(right, startCenter.Y));
                            this.endBasePoint = FormatPoint(new Point(right, endCenter.Y));
                            centerBasePoint = FormatPoint(new Point(startBasePoint.X, startBasePoint.Y + (endBasePoint.Y - startBasePoint.Y) / 2));
                        }
                        break;
                    }
            }

            //this.mainPathFigure.StartPoint = startPoint;
            //this.mainPolySegment.Points = new PointCollection(){
            //    this.startBasePoint,this.endBasePoint,endPoint,
            //};

            this.centerCPCtrl.CenterPoint = centerBasePoint;
            this.startCtrl.CenterPoint = startPoint;
            this.endCtrl.CenterPoint = endPoint;

            //只有这里，部件定义的中段线direction才是有效的。
            LocateTextPanel(this.startBasePoint, this.endBasePoint, this.direction);

            Tools.ArrowPoints apStart = new Tools.ArrowPoints(
                    startPoint, startBasePoint, Globals.MainWindow.EditorManager.DefaultFontSize);
            Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
                endPoint, endBasePoint, Globals.MainWindow.EditorManager.DefaultFontSize);

            switch (arrows)
            {
                //case ArrowType.All:
                //    {
                //        startArrowPath.Visibility = endArrowPath.Visibility = Visibility.Visible; break;
                //    }
                //case ArrowType.End:
                //    {
                //        startArrowPath.Visibility = Visibility.Hidden;
                //        endArrowPath.Visibility = Visibility.Visible;
                //        break;
                //    }
                //case ArrowType.Start:
                //    {
                //        startArrowPath.Visibility = Visibility.Visible;
                //        endArrowPath.Visibility = Visibility.Hidden;
                //        break;
                //    }
                //case ArrowType.None:
                //    {
                //        startArrowPath.Visibility = endArrowPath.Visibility = Visibility.Hidden; break;
                //    }
                case ArrowType.All:
                    {
                        this.startArrowPathFigure.StartPoint = apStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apStart.ArrowLeftPoint, apStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = apEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apEnd.ArrowLeftPoint, apEnd.ArrowRightPoint,
                        };

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = true;

                        this.mainPathFigure.StartPoint = startPoint;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetLineColor;
                        EndArrowPath.Fill = WidgetLineColor;

                        startArrowPath.Visibility = endArrowPath.Visibility = Visibility.Visible; break;
                    }
                case ArrowType.End:
                    {
                        this.startArrowPathFigure.StartPoint = apStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apStart.ArrowLeftPoint, apStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = apEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apEnd.ArrowLeftPoint, apEnd.ArrowRightPoint,
                        };

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = true;

                        this.mainPathFigure.StartPoint = startPoint;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,apEnd.ArrowRealTopPoint,
                        };

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = true;

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetLineColor;
                        EndArrowPath.Fill = WidgetLineColor;

                        startArrowPath.Visibility = Visibility.Hidden;
                        endArrowPath.Visibility = Visibility.Visible;
                        break;
                    }
                case ArrowType.Start:
                    {
                        this.startArrowPathFigure.StartPoint = apStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apStart.ArrowLeftPoint, apStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = apEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apEnd.ArrowLeftPoint, apEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = true;

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetLineColor;
                        EndArrowPath.Fill = WidgetLineColor;

                        startArrowPath.Visibility = Visibility.Visible;
                        endArrowPath.Visibility = Visibility.Hidden;
                        break;
                    }
                case ArrowType.None:
                    {
                        this.startArrowPathFigure.StartPoint = apStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apStart.ArrowLeftPoint, apStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = apEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apEnd.ArrowLeftPoint, apEnd.ArrowRightPoint,
                        };

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = true;

                        this.mainPathFigure.StartPoint = startPoint;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetLineColor;
                        EndArrowPath.Fill = WidgetLineColor;
                        startArrowPath.Visibility = endArrowPath.Visibility = Visibility.Hidden; break;
                    }
                case ArrowType.EmptyStart:
                    {
                        this.startArrowPathFigure.StartPoint = apStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apStart.ArrowLeftPoint, apStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = apEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apEnd.ArrowLeftPoint, apEnd.ArrowRightPoint,
                        };

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = true;

                        this.mainPathFigure.StartPoint = apStart.ArrowCenter;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = widgetBackColor;
                        EndArrowPath.Fill = WidgetLineColor;
                        startArrowPath.Visibility = Visibility.Visible;
                        endArrowPath.Visibility = Visibility.Hidden;
                        break;
                    }
                case ArrowType.RhombStart:
                    {
                        this.startArrowPathFigure.StartPoint = apStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apStart.ArrowLeftPoint, apStart.ArrowBottom, apStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = apEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apEnd.ArrowLeftPoint, apEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = apStart.ArrowBottom;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = true;

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetLineColor;
                        EndArrowPath.Fill = WidgetLineColor;

                        startArrowPath.Visibility = Visibility.Visible;
                        endArrowPath.Visibility = Visibility.Hidden;
                        break;
                    }
                case ArrowType.EmptyRhombStart:
                    {
                        this.startArrowPathFigure.StartPoint = apStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apStart.ArrowLeftPoint, apStart.ArrowBottom, apStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = apEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apEnd.ArrowLeftPoint, apEnd.ArrowRightPoint,
                        };

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = true;

                        this.mainPathFigure.StartPoint = apStart.ArrowBottom;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetBackColor;
                        EndArrowPath.Fill = WidgetLineColor;

                        startArrowPath.Visibility = Visibility.Visible;
                        endArrowPath.Visibility = Visibility.Hidden;
                        break;
                    }
                case ArrowType.Arrow:
                    {
                        this.startArrowPathFigure.StartPoint = apStart.ArrowRealTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apStart.ArrowLeftTop,apStart.ArrowLeftPoint, apStart.ArrowBottom,apStart.ArrowRightPoint,apStart.ArrowRightTop,
                        };

                        this.endArrowPathFigure.StartPoint = apEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apEnd.ArrowLeftPoint, apEnd.ArrowRightPoint,
                        };

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = true;

                        this.mainPathFigure.StartPoint = apStart.ArrowBottom;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetLineColor;
                        EndArrowPath.Fill = WidgetLineColor;

                        startArrowPath.Visibility = Visibility.Visible;
                        endArrowPath.Visibility = Visibility.Visible;
                        break;
                    }
                case ArrowType.EmptyArrow:
                    {
                        this.startArrowPathFigure.StartPoint = apStart.ArrowRealTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apStart.ArrowLeftTop,apStart.ArrowLeftPoint, apStart.ArrowBottom,apStart.ArrowRightPoint,apStart.ArrowRightTop,
                        };

                        this.endArrowPathFigure.StartPoint = apEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apEnd.ArrowLeftPoint, apEnd.ArrowRightPoint,
                        };

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = true;

                        this.mainPathFigure.StartPoint = apStart.ArrowBottom;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetBackColor;
                        EndArrowPath.Fill = WidgetBackColor;

                        startArrowPath.Visibility = Visibility.Visible;
                        endArrowPath.Visibility = Visibility.Visible;
                        break;
                    }
                case ArrowType.OpenArrowEnd:
                    {
                        this.startArrowPathFigure.StartPoint = apStart.ArrowRealTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apStart.ArrowLeftTop,apStart.ArrowLeftPoint, apStart.ArrowBottom,apStart.ArrowRightPoint,apStart.ArrowRightTop,
                        };

                        this.endArrowPathFigure.StartPoint = apEnd.ArrowLeftPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            apEnd.ArrowTopPoint, apEnd.ArrowRightPoint,
                        };

                        startArrowPathFigure.IsClosed = true;
                        endArrowPathFigure.IsClosed = false;

                        this.mainPathFigure.StartPoint = startPoint;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetBackColor;
                        EndArrowPath.Fill = Brushes.Transparent;

                        startArrowPath.Visibility = Visibility.Hidden;
                        endArrowPath.Visibility = Visibility.Visible;
                        break;
                    }
            }

            //重新计算箭头位置。
            //startArrowPathFigure.StartPoint = startPoint;
            //Tools.ArrowPoints apStart = new Tools.ArrowPoints(
            //        startArrowPathFigure.StartPoint, startBasePoint, widgetLineWidth * 2);

            //startArrowPolyLineSegment.Points = new PointCollection()
            //{
            //    apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
            //};
            //mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;

            //endArrowPathFigure.StartPoint = endPoint;
            //Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
            //    endArrowPathFigure.StartPoint, endBasePoint, widgetLineWidth * 2);
            //this.endArrowPolyLineSegment.Points = new PointCollection()
            //{
            //    apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
            //};

            return true;
        }

        /// <summary>
        /// 绘制L形线（∟形线|拐形线）。只在作连接线时有效。
        /// </summary>
        /// <param name="startRect">首挂接节点区域。</param>
        /// <param name="endRect">尾挂接节点区域。</param>
        private bool DrawLLine(Rect startRect, Rect endRect)
        {
            double padding = this.widgetLineWidth;
            endRect = new Rect(endRect.X - padding, endRect.Y - padding, endRect.Width + 2 * padding, endRect.Height + 2 * padding);

            Point startCenter = new Point(startRect.X + startRect.Width / 2, startRect.Y + startRect.Height / 2);
            Point endCenter = new Point(endRect.X + endRect.Width / 2, endRect.Y + endRect.Height / 2);

            Point startPoint;
            Point endPoint;

            switch (this.Direction)
            {
                case Orientation.Horizontal:
                    {
                        if (startCenter.X <= endCenter.X)//EndRect在右侧
                        {
                            if (startCenter.Y <= endCenter.Y)//End在右下
                            {
                                startPoint = this.FormatPoint(new Point(startRect.Right, startCenter.Y));
                                endPoint = this.FormatPoint(new Point(endCenter.X, endRect.Top));
                            }
                            else//End在右上
                            {
                                startPoint = this.FormatPoint(new Point(startRect.Right, startCenter.Y));
                                endPoint = this.FormatPoint(new Point(endCenter.X, endRect.Bottom));
                            }
                        }
                        else//EndRect在左侧
                        {
                            if (startCenter.Y <= endCenter.Y)//End在左下
                            {
                                startPoint = this.FormatPoint(new Point(startRect.Left, startCenter.Y));
                                endPoint = this.FormatPoint(new Point(endCenter.X, endRect.Top));
                            }
                            else//End在左上
                            {
                                startPoint = this.FormatPoint(new Point(startRect.Left, startCenter.Y));
                                endPoint = this.FormatPoint(new Point(endCenter.X, endRect.Bottom));
                            }
                        }

                        this.startBasePoint =
                            this.endBasePoint = new Point(endPoint.X, startPoint.Y);

                        //注意：this.centerBasePoint的取值不是中段线而是末段线：
                        this.centerBasePoint = this.FormatPoint(new Point(
                            endPoint.X, endPoint.Y + (startPoint.Y - endPoint.Y) / 2));
                        break;
                    }
                default:
                    {
                        if (startCenter.X <= endCenter.X)//EndRect在右侧
                        {
                            if (startCenter.Y <= endCenter.Y)//End在右下
                            {
                                startPoint = this.FormatPoint(new Point(startCenter.X, startRect.Bottom));
                                endPoint = this.FormatPoint(new Point(endRect.Left, endCenter.Y));
                            }
                            else//End在右上
                            {
                                startPoint = this.FormatPoint(new Point(startCenter.X, startRect.Top));
                                endPoint = this.FormatPoint(new Point(endRect.Left, endCenter.Y));
                            }
                        }
                        else//EndRect在左侧
                        {
                            if (startCenter.Y <= endCenter.Y)//End在左下
                            {
                                startPoint = this.FormatPoint(new Point(startCenter.X, startRect.Bottom));
                                endPoint = this.FormatPoint(new Point(endRect.Right, endCenter.Y));
                            }
                            else//End在左上
                            {
                                startPoint = this.FormatPoint(new Point(startCenter.X, startRect.Top));
                                endPoint = this.FormatPoint(new Point(endRect.Right, endCenter.Y));
                            }
                        }

                        this.startBasePoint =
                            this.endBasePoint = new Point(startPoint.X, endPoint.Y);
                        this.centerBasePoint = this.FormatPoint(new Point(
                            endPoint.X + (startPoint.X - endPoint.X) / 2, endPoint.Y));
                        break;
                    }
            }

            //只有这里，部件定义的中段线direction才是有效的。
            LocateTextPanel(this.startBasePoint, this.endBasePoint, this.direction);

            var aptStart = new ArrowPoints(startPoint, startBasePoint, Globals.MainWindow.EditorManager.DefaultFontSize);
            var aptEnd = new ArrowPoints(endPoint, endBasePoint, Globals.MainWindow.EditorManager.DefaultFontSize);

            switch (arrows)
            {
                case ArrowType.All:
                    {
                        this.startArrowPathFigure.StartPoint = aptStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            aptStart.ArrowLeftPoint, aptStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = aptEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            aptEnd.ArrowLeftPoint, aptEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = aptStart.ArrowRealTopPoint;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,aptEnd.ArrowRealTopPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetLineColor;
                        EndArrowPath.Fill = WidgetLineColor;

                        startArrowPath.Visibility = endArrowPath.Visibility = Visibility.Visible; break;
                    }
                case ArrowType.End:
                    {
                        this.startArrowPathFigure.StartPoint = aptStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            aptStart.ArrowLeftPoint, aptStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = aptEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            aptEnd.ArrowLeftPoint, aptEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = startPoint;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetLineColor;
                        EndArrowPath.Fill = WidgetLineColor;

                        startArrowPath.Visibility = Visibility.Hidden;
                        endArrowPath.Visibility = Visibility.Visible;
                        break;
                    }
                case ArrowType.Start:
                    {
                        this.startArrowPathFigure.StartPoint = aptStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            aptStart.ArrowLeftPoint, aptStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = aptEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            aptEnd.ArrowLeftPoint, aptEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = startPoint;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetLineColor;
                        EndArrowPath.Fill = WidgetLineColor;

                        startArrowPath.Visibility = Visibility.Visible;
                        endArrowPath.Visibility = Visibility.Hidden;
                        break;
                    }
                case ArrowType.None:
                    {
                        this.startArrowPathFigure.StartPoint = aptStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            aptStart.ArrowLeftPoint, aptStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = aptEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            aptEnd.ArrowLeftPoint, aptEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = startPoint;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetLineColor;
                        EndArrowPath.Fill = WidgetLineColor;
                        startArrowPath.Visibility = endArrowPath.Visibility = Visibility.Hidden; break;
                    }
                case ArrowType.EmptyStart:
                    {
                        this.startArrowPathFigure.StartPoint = aptStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            aptStart.ArrowLeftPoint, aptStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = aptEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            aptEnd.ArrowLeftPoint, aptEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = startPoint;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = widgetBackColor;
                        EndArrowPath.Fill = WidgetLineColor;
                        startArrowPath.Visibility = Visibility.Visible;
                        endArrowPath.Visibility = Visibility.Hidden;
                        break;
                    }
                case ArrowType.RhombStart:
                    {
                        this.startArrowPathFigure.StartPoint = aptStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            aptStart.ArrowLeftPoint, aptStart.ArrowBottom, aptStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = aptEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            aptEnd.ArrowLeftPoint, aptEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = aptStart.ArrowBottom;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,aptEnd.ArrowRealTopPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetLineColor;
                        EndArrowPath.Fill = WidgetLineColor;

                        startArrowPath.Visibility = Visibility.Visible;
                        endArrowPath.Visibility = Visibility.Hidden;
                        break;
                    }
                case ArrowType.EmptyRhombStart:
                    {
                        this.startArrowPathFigure.StartPoint = aptStart.ArrowTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            aptStart.ArrowLeftPoint, aptStart.ArrowBottom, aptStart.ArrowRightPoint,
                        };

                        this.endArrowPathFigure.StartPoint = aptEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            aptEnd.ArrowLeftPoint, aptEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = aptStart.ArrowBottom;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetBackColor;
                        EndArrowPath.Fill = WidgetLineColor;

                        startArrowPath.Visibility = Visibility.Visible;
                        endArrowPath.Visibility = Visibility.Hidden;
                        break;
                    }
                case ArrowType.Arrow:
                    {
                        this.startArrowPathFigure.StartPoint = aptStart.ArrowRealTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            aptStart.ArrowLeftTop,aptStart.ArrowLeftPoint, aptStart.ArrowBottom,aptStart.ArrowRightPoint,aptStart.ArrowRightTop,
                        };

                        this.endArrowPathFigure.StartPoint = aptEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            aptEnd.ArrowLeftPoint, aptEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = aptStart.ArrowBottom;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetLineColor;
                        EndArrowPath.Fill = WidgetLineColor;

                        startArrowPath.Visibility = Visibility.Visible;
                        endArrowPath.Visibility = Visibility.Visible;
                        break;
                    }
                case ArrowType.EmptyArrow:
                    {
                        this.startArrowPathFigure.StartPoint = aptStart.ArrowRealTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            aptStart.ArrowLeftTop,aptStart.ArrowLeftPoint, aptStart.ArrowBottom,aptStart.ArrowRightPoint,aptStart.ArrowRightTop,
                        };

                        this.endArrowPathFigure.StartPoint = aptEnd.ArrowTopPoint;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            aptEnd.ArrowLeftPoint, aptEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = aptStart.ArrowBottom;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,endPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetBackColor;
                        EndArrowPath.Fill = WidgetBackColor;

                        startArrowPath.Visibility = Visibility.Visible;
                        endArrowPath.Visibility = Visibility.Visible;
                        break;
                    }
                case ArrowType.OpenArrowEnd:
                    {
                        this.startArrowPathFigure.StartPoint = aptStart.ArrowRealTopPoint;
                        this.startArrowPolyLineSegment.Points = new PointCollection()
                        {
                            aptStart.ArrowLeftTop,aptStart.ArrowLeftPoint, aptStart.ArrowBottom,aptStart.ArrowRightPoint,aptStart.ArrowRightTop,
                        };

                        this.endArrowPathFigure.StartPoint = aptEnd.ArrowCenter;
                        this.endArrowPolyLineSegment.Points = new PointCollection()
                        {
                            aptEnd.ArrowLeftPoint, aptEnd.ArrowRightPoint,
                        };

                        this.mainPathFigure.StartPoint = aptStart.ArrowTopPoint;
                        this.mainPolySegment.Points = new PointCollection(){
                            this.startBasePoint,this.endBasePoint,aptEnd.ArrowTopPoint,
                        };

                        this.centerCPCtrl.CenterPoint = centerBasePoint;
                        this.startCtrl.CenterPoint = startPoint;
                        this.endCtrl.CenterPoint = endPoint;

                        StartArrowPath.Fill = WidgetBackColor;
                        EndArrowPath.Fill = Brushes.Transparent;

                        startArrowPath.Visibility = Visibility.Hidden;
                        endArrowPath.Visibility = Visibility.Visible;
                        break;
                    }
            }

            //重新计算箭头位置。
            //startArrowPathFigure.StartPoint = startPoint;
            //Tools.ArrowPoints apStart = new Tools.ArrowPoints(
            //        startArrowPathFigure.StartPoint, startBasePoint, widgetLineWidth * 2);

            //startArrowPolyLineSegment.Points = new PointCollection()
            //{
            //    apStart.ArrowLeftPoint,apStart.ArrowRightPoint,
            //};
            //mainPathFigure.StartPoint = apStart.ArrowRealTopPoint;

            //endArrowPathFigure.StartPoint = endPoint;
            //Tools.ArrowPoints apEnd = new Tools.ArrowPoints(
            //    endArrowPathFigure.StartPoint, endBasePoint, widgetLineWidth * 2);
            //this.endArrowPolyLineSegment.Points = new PointCollection()
            //{
            //    apEnd.ArrowLeftPoint,apEnd.ArrowRightPoint,
            //};

            return true;
        }

        private bool DrawBigFishBone(Rect startRect, Rect endRect)
        {
            Point startCenter = new Point(startRect.X + startRect.Width / 2, startRect.Y + startRect.Height / 2);
            if (startCenter.Y >= endRect.Top && startCenter.Y <= endRect.Bottom) return false;

            Point endCenter = new Point(endRect.X + endRect.Width / 2, endRect.Y + endRect.Height / 2);

            Point startPoint;
            Point endPoint;
            Point centerPoint;

            if (endCenter.X > startCenter.X)
            {
                startPoint = new Point(startRect.Right, startCenter.Y);

                if (endCenter.Y > startCenter.Y)
                {
                    endPoint = new Point(endCenter.X, endRect.Top);
                    centerPoint = new Point(endPoint.X - Math.Abs(endPoint.Y - startCenter.Y) / Math.Sqrt(3),
                        startCenter.Y);

                    if (centerPoint.X < startRect.Right) return false;//空间不够。
                }
                else
                {
                    endPoint = new Point(endCenter.X, endRect.Bottom);
                    centerPoint = new Point(endPoint.X - Math.Abs(endPoint.Y - startCenter.Y) / Math.Sqrt(3),
                        startCenter.Y);

                    if (centerPoint.X < startRect.Right) return false;//空间不够。
                }
            }
            else
            {
                startPoint = new Point(startRect.Left, startCenter.Y);

                if (endCenter.Y > startCenter.Y)
                {
                    endPoint = new Point(endCenter.X, endRect.Top);
                    centerPoint = new Point(endPoint.X + Math.Abs(endPoint.Y - startCenter.Y) / Math.Sqrt(3),
                        startCenter.Y);

                    if (centerPoint.X > startRect.Left) return false;//空间不够。
                }
                else
                {
                    endPoint = new Point(endCenter.X, endRect.Bottom);
                    centerPoint = new Point(endPoint.X + Math.Abs(endPoint.Y - startCenter.Y) / Math.Sqrt(3),
                        startCenter.Y);

                    if (centerPoint.X > startRect.Left) return false;//空间不够。
                }
            }

            startPoint = FormatPoint(startPoint);
            endPoint = FormatPoint(endPoint);
            centerPoint = FormatPoint(centerPoint);

            this.startPoint = startPoint; this.endPoint = endPoint; this.centerCPPoint = centerPoint;//刷新控制点位置。

            this.mainPathFigure.StartPoint = startPoint;
            this.mainPolySegment.Points = new PointCollection(){
                        centerPoint, endPoint
                    };

            this.centerCPCtrl.CenterPoint = centerPoint;
            this.startCtrl.CenterPoint = startPoint;
            this.endCtrl.CenterPoint = endPoint;
            //鱼骨图不显示箭头。
            this.startArrowPath.Visibility = this.endArrowPath.Visibility =

                this.centerCPCtrl.Visibility =
                    Visibility.Collapsed;
            return true;
        }

        private bool DrawMediumFishBone(Rect startRect, Rect endRect)
        {
            double padding = this.widgetLineWidth;
            endRect = new Rect(endRect.X - padding, endRect.Y - padding, endRect.Width + 2 * padding, endRect.Height + 2 * padding);

            Point startCenter = new Point(startRect.X + startRect.Width / 2, startRect.Y + startRect.Height / 2);
            Point endCenter = new Point(endRect.X + endRect.Width / 2, endRect.Y + endRect.Height / 2);

            //if (startCenter.Y >= endRect.Top && startCenter.Y <= endRect.Bottom) return false;//中骨只显示横线

            Point startPoint;
            Point endPoint;
            Point startCPPoint;
            Point endCPPoint;
            Point endBasePoint;

            double d = Math.Sqrt(3);

            if (endCenter.X > startCenter.X)
            {
                startPoint = new Point(startRect.Right, startCenter.Y);

                if (endCenter.Y > startCenter.Y)
                {
                    endBasePoint = endRect.BottomLeft;
                    endCPPoint = new Point(endBasePoint.X - endRect.Height / d, endBasePoint.Y - endRect.Height);
                    endPoint = new Point(endRect.Right, endCPPoint.Y);
                    startCPPoint = new Point(endRect.Left - Math.Abs(endRect.Bottom - startCenter.Y) / d, startCenter.Y);

                    //if (startCPPoint.X < startRect.Right) return false;//空间不够。//中骨只显示横线
                }
                else
                {
                    endBasePoint = endRect.TopLeft;
                    endCPPoint = new Point(endBasePoint.X - endRect.Height / d, endBasePoint.Y + endRect.Height);
                    endPoint = new Point(endRect.Right, endCPPoint.Y);
                    startCPPoint = new Point(endRect.Left - Math.Abs(endRect.Top - startCenter.Y) / d, startCenter.Y);

                    //if (startCPPoint.X < startRect.Right) return false;//空间不够。//中骨只显示横线
                }
            }
            else
            {
                startPoint = new Point(startRect.Left, startCenter.Y);

                if (endCenter.Y > startCenter.Y)
                {
                    endBasePoint = endRect.BottomRight;
                    endCPPoint = new Point(endBasePoint.X + endRect.Height / d, endBasePoint.Y - endRect.Height);
                    endPoint = new Point(endRect.Left, endCPPoint.Y);
                    startCPPoint = new Point(endRect.Right + Math.Abs(endRect.Bottom - startCenter.Y) / d, startCenter.Y);

                    //if (startCPPoint.X > startRect.Left) return false;//空间不够。//中骨只显示横线
                }
                else
                {
                    endBasePoint = endRect.TopRight;
                    endCPPoint = new Point(endBasePoint.X + endRect.Height / d, endBasePoint.Y + endRect.Height);
                    endPoint = new Point(endRect.Left, endCPPoint.Y);
                    startCPPoint = new Point(endRect.Right + Math.Abs(endRect.Top - startCenter.Y) / d, startCenter.Y);

                    //if (startCPPoint.X > startRect.Left) return false;//空间不够。//中骨只显示横线
                }
            }

            startPoint = FormatPoint(startPoint);
            endPoint = FormatPoint(endPoint);
            startCPPoint = FormatPoint(startCPPoint);

            this.startPoint = startPoint; this.endPoint = endPoint; this.centerCPPoint = startCPPoint;//刷新控制点位置。

            //this.mainPathFigure.StartPoint = startPoint;
            //this.mainPolySegment.Points = new PointCollection(){
            //            startCPPoint,endCPPoint,endPoint
            //        };

            //中骨不显示斜线，但计算斜线
            this.mainPathFigure.StartPoint = endCPPoint;
            this.mainPolySegment.Points = new PointCollection(){
                endPoint,
            };

            this.centerCPCtrl.CenterPoint = startCPPoint;
            this.startCtrl.CenterPoint = startPoint;
            this.endCtrl.CenterPoint = endPoint;
            //鱼骨图不显示箭头。
            this.startArrowPath.Visibility = this.endArrowPath.Visibility =

                this.centerCPCtrl.Visibility =
                    Visibility.Collapsed;

            return true;
        }

        /// <summary>
        /// 重定文本位置。
        /// </summary>
        /// <param name="startBasePoint">首基准点。</param>
        /// <param name="endBasePoint">尾基准点。</param>
        /// <param name="centerCPPoint">中基准点。</param>
        /// <param name="derection">中段线指向。</param>
        private void LocateTextPanel(Point startBasePoint, Point endBasePoint, Orientation direction)
        {
            switch (this.LineForm)
            {
                case PolyLineForms.CLine:
                case PolyLineForms.PolyLine:
                    {
                        Point textStart;
                        if (isTextAtLeftOrTop)
                        {
                            switch (direction)
                            {
                                case Orientation.Horizontal:
                                    {
                                        textStart = new Point(centerBasePoint.X
                                            - this.mainBorder.ActualWidth / 2 - this.mainBorder.Margin.Left,
                                            centerBasePoint.Y - widgetLineWidth - this.mainBorder.Margin.Top
                                            - this.mainBorder.ActualHeight - 6);
                                        break;
                                    }
                                default:
                                    {
                                        textStart = new Point(
                                            centerBasePoint.X - widgetLineWidth + this.mainBorder.Margin.Left
                                            - this.mainBorder.ActualWidth - 6,
                                            centerBasePoint.Y
                                            - this.mainBorder.ActualHeight / 2 - this.mainBorder.Margin.Top);
                                        break;
                                    }
                            }
                        }
                        else
                        {
                            switch (direction)
                            {
                                case Orientation.Horizontal:
                                    {
                                        textStart = new Point(
                                            centerBasePoint.X
                                            - this.mainBorder.ActualWidth / 2 - this.mainBorder.Margin.Left,
                                            centerBasePoint.Y + widgetLineWidth + this.mainBorder.Margin.Top);
                                        break;
                                    }
                                default:
                                    {
                                        textStart = new Point(
                                            centerBasePoint.X + widgetLineWidth + this.mainBorder.Margin.Left,
                                            centerBasePoint.Y
                                            - this.mainBorder.ActualHeight / 2 - this.mainBorder.Margin.Top);
                                        break;
                                    }
                            }
                        }

                        Canvas.SetLeft(this.mainBorder, textStart.X);
                        Canvas.SetTop(this.mainBorder, textStart.Y);

                        break;
                    }
                case PolyLineForms.LLine:
                    {
                        //翻转纵横向（中段线与尾段正好成直角）按尾段而不是中段排列。
                        Point textStart;
                        if (isTextAtLeftOrTop)
                        {
                            switch (direction)
                            {
                                case Orientation.Vertical:
                                    {
                                        textStart = new Point(centerBasePoint.X
                                            - this.mainBorder.ActualWidth / 2 - this.mainBorder.Margin.Left,
                                            centerBasePoint.Y - widgetLineWidth - this.mainBorder.Margin.Top
                                            - this.mainBorder.ActualHeight - 6);
                                        break;
                                    }
                                default:
                                    {
                                        textStart = new Point(
                                            centerBasePoint.X - widgetLineWidth + this.mainBorder.Margin.Left
                                            - this.mainBorder.ActualWidth - 6,
                                            centerBasePoint.Y
                                            - this.mainBorder.ActualHeight / 2 - this.mainBorder.Margin.Top);
                                        break;
                                    }
                            }
                        }
                        else
                        {
                            switch (direction)
                            {
                                case Orientation.Vertical:
                                    {
                                        textStart = new Point(
                                            centerBasePoint.X
                                            - this.mainBorder.ActualWidth / 2 - this.mainBorder.Margin.Left,
                                            centerBasePoint.Y + widgetLineWidth + this.mainBorder.Margin.Top);
                                        break;
                                    }
                                default:
                                    {
                                        textStart = new Point(
                                            centerBasePoint.X + widgetLineWidth + this.mainBorder.Margin.Left,
                                            centerBasePoint.Y
                                            - this.mainBorder.ActualHeight / 2 - this.mainBorder.Margin.Top);
                                        break;
                                    }
                            }
                        }

                        Canvas.SetLeft(this.mainBorder, textStart.X);
                        Canvas.SetTop(this.mainBorder, textStart.Y);

                        break;
                    }
                default: break;//鱼骨图等不支持文本显示。
            }
        }

        public override void DropWidget(ModifingItem<Action, ModifingInfo> mi, Point mousePoint)
        {
            if (mi == null) return;

            Point globalLocation = masterEditor.MouseInfo.LeftButtonPreviewPoint;

            Point newStartPoint = new Point(
                startPoint.X - globalLocation.X + mousePoint.X, startPoint.Y - globalLocation.Y + mousePoint.Y);
            Action actStartPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.StartPointTag, startPoint.ToString(),
                newStartPoint.ToString());
            StartPoint = newStartPoint;

            Point newCenterCPPoint = new Point(
                centerCPPoint.X - globalLocation.X + mousePoint.X, centerCPPoint.Y - globalLocation.Y + mousePoint.Y);
            Action actCenterCPPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.CenterCPPointTag, centerCPPoint.ToString(),
                newCenterCPPoint.ToString());
            CenterCPPoint = newCenterCPPoint;

            Point newEndPoint = new Point(
                endPoint.X - globalLocation.X + mousePoint.X, endPoint.Y - globalLocation.Y + mousePoint.Y);
            Action actEndPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.EndPointTag, endPoint.ToString(),
                newEndPoint.ToString());
            EndPoint = newEndPoint;

            mi.ModifingInfo.NewMainSelectedWidgetID = this.id;
            mi.AddAction(actStartPoint);
            mi.AddAction(actCenterCPPoint);
            mi.AddAction(actEndPoint);

            this.RefreshCommentText();
            this.RefreshHyperLinkText();

            RefreshPresentateAdorners();
        }

        public override void DropWidgetControler(Point newMovingPoint, ModifingItem<Action, ModifingInfo> mi)
        {
            if (mi == null || mi.ModifingInfo == null) return;
            if (masterEditor == null || masterEditor.MasterManager == null) return;

            ModifingInfo info = mi.ModifingInfo;
            switch (draggingType)
            {
                case ControlDraggingType.Start:
                    {
                        info.ModifingDescription = "拖动折线首端点";

                        Action actDraggingLineHeader = new Action(masterEditor.Id, id, this.GetType().Name,
                            XmlTags.StartPointTag, startPoint.ToString(), newMovingPoint.ToString());
                        StartPoint = newMovingPoint;

                        info.NewMainSelectedWidgetID = this.id;
                        mi.AddAction(actDraggingLineHeader);
                        break;
                    }
                case ControlDraggingType.CenterCP:
                    {
                        info.ModifingDescription = "拖动折线控制点";

                        Action actDraggingLineHeader = new Action(masterEditor.Id, id, this.GetType().Name,
                            XmlTags.CenterCPPointTag, centerCPPoint.ToString(), newMovingPoint.ToString());
                        CenterCPPoint = newMovingPoint;

                        info.NewMainSelectedWidgetID = this.id;
                        mi.AddAction(actDraggingLineHeader);
                        break;
                    }
                case ControlDraggingType.End:
                    {
                        info.ModifingDescription = "拖动折线尾端点";

                        Action actDraggingLineHeader = new Action(masterEditor.Id, id, this.GetType().Name,
                            XmlTags.EndPointTag, endPoint.ToString(), newMovingPoint.ToString());
                        EndPoint = newMovingPoint;

                        info.NewMainSelectedWidgetID = this.id;
                        mi.AddAction(actDraggingLineHeader);
                        break;
                    }
            }

            this.RefreshCommentText();
            this.RefreshHyperLinkText();
            this.RefreshControlers();

            RefreshPresentateAdorners();
        }

        public override void CollapseToTop(ModifingItem<Action, ModifingInfo> mi, double units = 1)
        {
            if (mi == null) return;

            if (startPoint.Y > endPoint.Y)
            {
                Point newStartPoint = new Point(startPoint.X, startPoint.Y - units);
                Action actStartPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.StartPointTag,
                    startPoint.ToString(), newStartPoint.ToString());
                StartPoint = newStartPoint;

                mi.AddAction(actStartPoint);
            }
            else if (startPoint.Y < endPoint.Y)
            {
                Point newEndPoint = new Point(endPoint.X, endPoint.Y - units);
                Action actEndPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.EndPointTag,
                    endPoint.ToString(), newEndPoint.ToString());
                EndPoint = newEndPoint;

                mi.AddAction(actEndPoint);
            }
            //如果水平对齐，则不更改。
        }

        public override void ExpandToBottom(ModifingItem<Action, ModifingInfo> mi, double units = 1)
        {
            if (mi == null) return;

            if (startPoint.Y > endPoint.Y)
            {
                Point newStartPoint = new Point(startPoint.X, startPoint.Y + units);
                Action actStartPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.StartPointTag,
                    startPoint.ToString(), newStartPoint.ToString());
                StartPoint = newStartPoint;

                mi.AddAction(actStartPoint);
            }
            else if (startPoint.Y < endPoint.Y)
            {
                Point newEndPoint = new Point(endPoint.X, endPoint.Y + units);
                Action actEndPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.EndPointTag,
                    endPoint.ToString(), newEndPoint.ToString());
                EndPoint = newEndPoint;

                mi.AddAction(actEndPoint);
            }
            //如果水平对齐，则不更改。
        }

        public override void CollapseToLeft(ModifingItem<Action, ModifingInfo> mi, double units = 1)
        {
            if (mi == null) return;

            if (startPoint.X > endPoint.X)
            {
                Point newStartPoint = new Point(startPoint.X - units, startPoint.Y);
                Action actStartPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.StartPointTag,
                    startPoint.ToString(), newStartPoint.ToString());
                StartPoint = newStartPoint;

                mi.AddAction(actStartPoint);
            }
            else if (startPoint.X < endPoint.X)
            {
                Point newEndPoint = new Point(endPoint.X - units, endPoint.Y);
                Action actEndPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.EndPointTag,
                    endPoint.ToString(), newEndPoint.ToString());
                EndPoint = newEndPoint;

                mi.AddAction(actEndPoint);
            }
            //如果垂直对齐，则不更改
        }

        public override void ExpandToRight(ModifingItem<Action, ModifingInfo> mi, double units = 1)
        {
            if (mi == null) return;

            if (startPoint.X > endPoint.X)
            {
                Point newStartPoint = new Point(startPoint.X + units, startPoint.Y);
                Action actStartPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.StartPointTag,
                    startPoint.ToString(), newStartPoint.ToString());
                StartPoint = newStartPoint;

                mi.AddAction(actStartPoint);
            }
            else if (startPoint.X < endPoint.X)
            {
                Point newEndPoint = new Point(endPoint.X + units, endPoint.Y);
                Action actEndPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.EndPointTag,
                    endPoint.ToString(), newEndPoint.ToString());
                EndPoint = newEndPoint;

                mi.AddAction(actEndPoint);
            }
            //如果垂直对齐，则不更改
        }

        private Point FormatStartMovingPoint(Point newInsideMovingPoint, Point endPoint)
        {
            double horizontalDistance = newInsideMovingPoint.X - endPoint.X;
            double verticalDistance = newInsideMovingPoint.Y - endPoint.Y;

            double absHD = Math.Abs(horizontalDistance);
            double absVD = Math.Abs(verticalDistance);

            if (absVD > absHD)
            {
                if (absVD > absHD * 2)
                {
                    newInsideMovingPoint = new Point(endPoint.X, newInsideMovingPoint.Y);
                }
                else
                {
                    int qua = Getquadrant(newInsideMovingPoint, endPoint);
                    switch (qua)
                    {
                        case 1:
                            {
                                newInsideMovingPoint = new Point(newInsideMovingPoint.X,
                                   endPoint.Y - (newInsideMovingPoint.X - endPoint.X));
                                break;
                            }
                        case 2:
                            {
                                newInsideMovingPoint = new Point(newInsideMovingPoint.X,
                                   endPoint.Y + (newInsideMovingPoint.X - endPoint.X));
                                break;
                            }
                        case 3:
                            {
                                newInsideMovingPoint = new Point(newInsideMovingPoint.X,
                                   endPoint.Y - (newInsideMovingPoint.X - endPoint.X));
                                break;
                            }
                        case 4:
                            {
                                newInsideMovingPoint = new Point(newInsideMovingPoint.X,
                                    endPoint.Y + (newInsideMovingPoint.X - endPoint.X));
                                break;
                            }
                    }
                }
            }
            else
            {
                if (absVD * 2 < absHD)
                {
                    newInsideMovingPoint = new Point(newInsideMovingPoint.X, endPoint.Y);
                }
                else
                {
                    int qua = Getquadrant(newInsideMovingPoint, endPoint);
                    switch (qua)
                    {
                        case 1:
                            {
                                newInsideMovingPoint = new Point(newInsideMovingPoint.X,
                                   endPoint.Y - (newInsideMovingPoint.X - endPoint.X));
                                break;
                            }
                        case 2:
                            {
                                newInsideMovingPoint = new Point(newInsideMovingPoint.X,
                                   endPoint.Y + (newInsideMovingPoint.X - endPoint.X));
                                break;
                            }
                        case 3:
                            {
                                newInsideMovingPoint = new Point(newInsideMovingPoint.X,
                                   endPoint.Y - (newInsideMovingPoint.X - endPoint.X));
                                break;
                            }
                        case 4:
                            {
                                newInsideMovingPoint = new Point(newInsideMovingPoint.X,
                                    endPoint.Y + (newInsideMovingPoint.X - endPoint.X));
                                break;
                            }
                    }
                }
            }

            return newInsideMovingPoint;
        }

        /// <summary>
        /// 以basePoint为基础坐标，画出四象限。
        /// 取出pt在哪个象限中。
        /// </summary>
        /// <param name="pt"></param>
        /// <param name="basePoint"></param>
        /// <returns></returns>
        private int Getquadrant(Point pt, Point basePoint)
        {
            if (pt.X > basePoint.X)
            {
                if (pt.Y > basePoint.Y)
                {
                    return 4;
                }
                else
                {
                    return 1;
                }
            }
            else
            {
                if (pt.Y > basePoint.Y)
                {
                    return 3;
                }
                else
                {
                    return 2;
                }
            }
        }

        public override string GetRelativeOuterXml(Point baseCopyTopLeft)
        {
            if (this.xmlData == null) return string.Empty;

            Point oldStartPoint = startPoint;
            Point newStartPoint = new Point(oldStartPoint.X - baseCopyTopLeft.X,
                oldStartPoint.Y - baseCopyTopLeft.Y);
            this.xmlData.SetAttribute(XmlTags.StartPointTag, newStartPoint.ToString());

            Point oldCenterCPPoint = centerCPPoint;
            Point newCenterCPPoint = new Point(oldCenterCPPoint.X - baseCopyTopLeft.X,
                oldCenterCPPoint.Y - baseCopyTopLeft.Y);
            this.xmlData.SetAttribute(XmlTags.CenterCPPointTag, newCenterCPPoint.ToString());

            Point oldEndPoint = endPoint;
            Point newEndPoint = new Point(oldEndPoint.X - baseCopyTopLeft.X,
                oldEndPoint.Y - baseCopyTopLeft.Y);
            this.xmlData.SetAttribute(XmlTags.EndPointTag, newEndPoint.ToString());

            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            sb.Append(this.xmlData.OuterXml);

            this.xmlData.SetAttribute(XmlTags.StartPointTag, oldStartPoint.ToString());
            this.xmlData.SetAttribute(XmlTags.CenterCPPointTag, oldCenterCPPoint.ToString());
            this.xmlData.SetAttribute(XmlTags.EndPointTag, oldEndPoint.ToString());
            return sb.ToString();
        }

        void endArrowPath_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            endCtrl_MouseLeftButtonDown(sender, e);
        }

        void startArrowPath_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            startCtrl_MouseLeftButtonDown(sender, e);
        }

        public event EventHandler<MouseButtonEventArgs> ControlHandlerDoubleClicked;

        protected void OnControlHandlerDoubleClicked(object sender, MouseButtonEventArgs e)
        {
            if (ControlHandlerDoubleClicked != null)
            {
                ControlHandlerDoubleClicked(sender, e);
            }
        }

        void endCtrl_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (e.ClickCount == 2)
            {
                OnControlHandlerDoubleClicked(sender, e);
                e.Handled = true;
                return;
            }

            this.SelectOnlySelf();

            //if (this.IsLinked) return;//连接线需要更改挂接的目标部件

            //开始拖动。
            e.Handled = true;
            masterEditor.MouseInfo.LeftButtonPreviewPoint = endPoint;
            draggingType = ControlDraggingType.End;
            masterEditor.MouseInfo.DraggingType = Enums.PageDraggingType.MoveLineWidgetControler;

            endCtrl.Visibility = centerCPCtrl.Visibility = System.Windows.Visibility.Hidden;
        }

        void startCtrl_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (e.ClickCount == 2)
            {
                OnControlHandlerDoubleClicked(sender, e);
                e.Handled = true;
                return;
            }

            this.SelectOnlySelf();

            //if (this.IsLinked) return;//连接线需要更改挂接的目标部件

            //开始拖动。
            e.Handled = true;
            masterEditor.MouseInfo.LeftButtonPreviewPoint = startPoint;
            draggingType = ControlDraggingType.Start;
            masterEditor.MouseInfo.DraggingType = Enums.PageDraggingType.MoveLineWidgetControler;

            startCtrl.Visibility = centerCPCtrl.Visibility = System.Windows.Visibility.Hidden;
        }

        /// <summary>
        /// 这个虚方法是用以查看本部件是否在选定框的内部。
        /// 线型部件，各有各的计算办法。
        /// </summary>
        /// <param name="rect"></param>
        /// <returns></returns>
        public override bool IsInRect(Rect rect)
        {
            //return base.IsInRect(rect);//这个要屏蔽。
            bool isInRect = base.IsInRect(rect);
            if (isInRect)
            {
                return true;
            }
            else
            {
                //这个法子还不完善。线是否“穿过”矩形还得另想办法。
                //return rect.Contains(startPoint) || rect.Contains(endPoint) ||
                //    rect.Contains(CenterCPPoint);

                if (this.IsLinked)//2012年10月15日
                {
                    return rect.Contains(this.startCtrl.CenterPoint) || rect.Contains(this.endCtrl.CenterPoint);
                }
                else
                {
                    return rect.Contains(this.startCtrl.CenterPoint) || rect.Contains(this.endCtrl.CenterPoint) ||
                        rect.Contains(this.centerCPCtrl.CenterPoint);
                }
            }
        }

        void mainPath_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            //双击编辑文本
            if (e.ClickCount == 2)
            {
                this.SelectOnlySelf();
                if (Globals.MainWindow.IsPresentatingByPath == false)
                {
                    this.Edit();
                }
                return;
            }

            ModifingItem<Action, ModifingInfo> mi = null;
            ModifingInfo info = null;
            if (FormatSelf(ref mi, ref info))
            {
                if (masterEditor != null)
                {
                    masterEditor.MouseInfo.DraggingType = Enums.PageDraggingType.MoveWidgets;
                }
                return;//格式刷格式化，不更改选定状态。
            }

            KeyStates ksRightShift = Keyboard.GetKeyStates(Key.RightShift);
            KeyStates ksLeftShift = Keyboard.GetKeyStates(Key.LeftShift);

            bool isShift = false;

            if ((ksRightShift & KeyStates.Down) > 0 || (ksLeftShift & KeyStates.Down) > 0) { isShift = true; }

            bool isCtrl = false;
            KeyStates ksRightCtrl = Keyboard.GetKeyStates(Key.RightCtrl);
            KeyStates ksLeftCtrl = Keyboard.GetKeyStates(Key.LeftCtrl);

            if ((ksRightCtrl & KeyStates.Down) > 0 || (ksLeftCtrl & KeyStates.Down) > 0) isCtrl = true;

            if (isShift && isCtrl == false)
            {
                //基本规则：
                //    ①如果未选定，选定，并作为活动部件。
                //    ②如果已选定，看是否是活动部件，如果已经是活动部件，整个取消选定状态；
                //                                      如果不是活动部件，设为活动部件。
                if (this.IsSelected == false)
                {
                    this.IsMainSelected = true;
                }
                else
                {
                    if (this.IsMainSelected == false)
                    {
                        this.IsMainSelected = true;
                    }
                    else
                    {
                        this.IsSelected = false;
                    }
                }
            }
            else
            {
                if (IsSelected == false)
                {
                    this.SelectOnlySelf();
                }
                //如果是选定的部件，那么可能是在拖动。
            }

            //准备拖动。
            if (masterEditor != null)
            {
                masterEditor.MouseInfo.DraggingType = Enums.PageDraggingType.MoveWidgets;
                Point pt = e.GetPosition(this.masterEditor);
                pt = new Point(pt.X - this.masterEditor.BorderThickness.Left, pt.Y - this.masterEditor.BorderThickness.Top);
                masterEditor.MouseInfo.LeftButtonPreviewPoint = pt;
            }
        }

        void mainPath_PreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;

            if (this.IsSelected == false)
            {
                //如果未选定，就作为活动，
                this.SelectOnlySelf();
            }
            else
            {
                //若已选定，不更改选定范围，只更改“活动部件”为此部件
                if (this.IsMainSelected == false) this.IsMainSelected = true;
            }

            if (this.ContextMenu != null)
            {
                this.ContextMenu.IsOpen = true;
            }
        }

        public override void MoveUp(ModifingItem<Action, ModifingInfo> mi, double units = 1)
        {
            if (mi == null) return;

            Point newStartPoint = new Point(startPoint.X, startPoint.Y - units);
            Action actStartPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.StartPointTag,
                startPoint.ToString(), newStartPoint.ToString());
            StartPoint = newStartPoint;

            Point newCenterCPPoint = new Point(centerCPPoint.X, centerCPPoint.Y - units);
            Action actStartCPPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.CenterCPPointTag,
                centerCPPoint.ToString(), newCenterCPPoint.ToString());
            CenterCPPoint = newCenterCPPoint;

            Point newEndPoint = new Point(endPoint.X, endPoint.Y - units);
            Action actEndPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.EndPointTag,
                endPoint.ToString(), newEndPoint.ToString());
            EndPoint = newEndPoint;

            mi.AddAction(actStartPoint);
            mi.AddAction(actStartCPPoint);
            mi.AddAction(actEndPoint);
        }

        public override void MoveDown(ModifingItem<Action, ModifingInfo> mi, double units = 1)
        {
            if (mi == null) return;

            Point newStartPoint = new Point(startPoint.X, startPoint.Y + units);
            Action actStartPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.StartPointTag,
                startPoint.ToString(), newStartPoint.ToString());
            StartPoint = newStartPoint;

            Point newCenterCPPoint = new Point(centerCPPoint.X, centerCPPoint.Y + units);
            Action actStartCPPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.CenterCPPointTag,
                centerCPPoint.ToString(), newCenterCPPoint.ToString());
            CenterCPPoint = newCenterCPPoint;

            Point newEndPoint = new Point(endPoint.X, endPoint.Y + units);
            Action actEndPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.EndPointTag,
                endPoint.ToString(), newEndPoint.ToString());
            EndPoint = newEndPoint;

            mi.AddAction(actStartPoint);
            mi.AddAction(actStartCPPoint);
            mi.AddAction(actEndPoint);
        }

        public override void MoveLeft(ModifingItem<Action, ModifingInfo> mi, double units = 1)
        {
            if (mi == null) return;

            Point newStartPoint = new Point(startPoint.X - units, startPoint.Y);
            Action actStartPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.StartPointTag,
                startPoint.ToString(), newStartPoint.ToString());
            StartPoint = newStartPoint;

            Point newCenterCPPoint = new Point(centerCPPoint.X - units, centerCPPoint.Y);
            Action actStartCPPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.CenterCPPointTag,
                centerCPPoint.ToString(), newCenterCPPoint.ToString());
            CenterCPPoint = newCenterCPPoint;

            Point newEndPoint = new Point(endPoint.X - units, endPoint.Y);
            Action actEndPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.EndPointTag,
                endPoint.ToString(), newEndPoint.ToString());
            EndPoint = newEndPoint;

            mi.AddAction(actStartPoint);
            mi.AddAction(actStartCPPoint);
            mi.AddAction(actEndPoint);
        }

        public override void MoveRight(ModifingItem<Action, ModifingInfo> mi, double units = 1)
        {
            if (mi == null) return;

            Point newStartPoint = new Point(startPoint.X + units, startPoint.Y);
            Action actStartPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.StartPointTag,
                startPoint.ToString(), newStartPoint.ToString());
            StartPoint = newStartPoint;

            Point newCenterCPPoint = new Point(centerCPPoint.X + units, centerCPPoint.Y);
            Action actCenterCPPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.CenterCPPointTag,
                centerCPPoint.ToString(), newCenterCPPoint.ToString());
            CenterCPPoint = newCenterCPPoint;

            Point newEndPoint = new Point(endPoint.X + units, endPoint.Y);
            Action actEndPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.EndPointTag,
                endPoint.ToString(), newEndPoint.ToString());
            EndPoint = newEndPoint;

            mi.AddAction(actStartPoint);
            mi.AddAction(actCenterCPPoint);
            mi.AddAction(actEndPoint);
        }

        /// <summary>
        /// 改变中心点横坐标。
        /// ★注意：CenterCPPoint并不是逻辑中心点。
        /// </summary>
        public override void MoveHorizontalCenterTo(ModifingItem<Action, ModifingInfo> mi, double center)
        {
            if (mi == null || double.IsNaN(center) || masterEditor == null) return;

            double offset = 0;
            double curCenter = TopLeft.X + (BottomRight.X - TopLeft.X) / 2;
            offset = curCenter - center;

            Point newStartPoint = new Point(startPoint.X - offset, startPoint.Y);
            Action actStart = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.StartPointTag,
                startPoint.ToString(), newStartPoint.ToString());
            this.StartPoint = newStartPoint;

            Point newCenterCPPoint = new Point(centerCPPoint.X - offset, centerCPPoint.Y);
            Action actCenterCP = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.CenterCPPointTag,
                centerCPPoint.ToString(), newCenterCPPoint.ToString());
            this.CenterCPPoint = newCenterCPPoint;

            Point newEndPoint = new Point(endPoint.X - offset, endPoint.Y);
            Action actEnd = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.EndPointTag,
                endPoint.ToString(), newEndPoint.ToString());
            this.EndPoint = newEndPoint;

            mi.AddAction(actStart);
            mi.AddAction(actCenterCP);
            mi.AddAction(actEnd);
        }

        /// <summary>
        /// 改变中心点纵坐标。
        /// ★注意：CenterCPPoint并不是逻辑中心点。
        /// </summary>
        public override void MoveVerticalCenterTo(ModifingItem<Action, ModifingInfo> mi, double center)
        {
            if (mi == null || double.IsNaN(center) || masterEditor == null) return;

            double offset = 0;
            double curCenter = TopLeft.Y + (BottomRight.Y - TopLeft.Y) / 2;
            offset = curCenter - center;

            Point newStartPoint = new Point(startPoint.X, startPoint.Y - offset);
            Action actStart = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.StartPointTag,
                startPoint.ToString(), newStartPoint.ToString());
            this.StartPoint = newStartPoint;

            Point newCenterCPPoint = new Point(centerCPPoint.X, centerCPPoint.Y - offset);
            Action actCenterCP = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.CenterCPPointTag,
                centerCPPoint.ToString(), newCenterCPPoint.ToString());
            this.CenterCPPoint = newCenterCPPoint;

            Point newEndPoint = new Point(endPoint.X, endPoint.Y - offset);
            Action actEnd = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.EndPointTag,
                endPoint.ToString(), newEndPoint.ToString());
            this.EndPoint = newEndPoint;

            mi.AddAction(actStart);
            mi.AddAction(actCenterCP);
            mi.AddAction(actEnd);
        }

        /// <summary>
        /// 与MoveDown不同，这里是指定向下移动到哪个位置（下边缘到哪个位置）。
        /// </summary>
        public override void MoveBottomSiderTo(ModifingItem<Action, ModifingInfo> mi, double bottom)
        {
            if (mi == null || double.IsNaN(bottom) || masterEditor == null) return;

            double offset = 0;
            double maxBottom = BottomRight.Y;
            offset = maxBottom - bottom;

            Point newStartPoint = new Point(startPoint.X, startPoint.Y - offset);
            Action actStart = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.StartPointTag,
                startPoint.ToString(), newStartPoint.ToString());
            this.StartPoint = newStartPoint;

            Point newCenterCPPoint = new Point(centerCPPoint.X, centerCPPoint.Y - offset);
            Action actCenterCP = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.CenterCPPointTag,
                centerCPPoint.ToString(), newCenterCPPoint.ToString());
            this.CenterCPPoint = newCenterCPPoint;

            Point newEndPoint = new Point(endPoint.X, endPoint.Y - offset);
            Action actEnd = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.EndPointTag,
                endPoint.ToString(), newEndPoint.ToString());
            this.EndPoint = newEndPoint;

            mi.AddAction(actStart);
            mi.AddAction(actCenterCP);
            mi.AddAction(actEnd);
        }

        /// <summary>
        /// 与MoveLeft不同，这里是指定向左移动到哪个位置（左边缘到哪个位置）。
        /// </summary>
        public override void MoveLeftSiderTo(ModifingItem<Action, ModifingInfo> mi, double left)
        {
            if (mi == null || double.IsNaN(left) || masterEditor == null) return;

            double offset = 0;
            double minLeft = TopLeft.X;
            offset = minLeft - left;

            Point newStartPoint = new Point(startPoint.X - offset, startPoint.Y);
            Action actStart = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.StartPointTag,
                startPoint.ToString(), newStartPoint.ToString());
            this.StartPoint = newStartPoint;

            Point newCenterCPPoint = new Point(centerCPPoint.X - offset, centerCPPoint.Y);
            Action actCenterCP = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.CenterCPPointTag,
                centerCPPoint.ToString(), newCenterCPPoint.ToString());
            this.CenterCPPoint = newCenterCPPoint;

            Point newEndPoint = new Point(endPoint.X - offset, endPoint.Y);
            Action actEnd = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.EndPointTag,
                endPoint.ToString(), newEndPoint.ToString());
            this.EndPoint = newEndPoint;

            mi.AddAction(actStart);
            mi.AddAction(actCenterCP);
            mi.AddAction(actEnd);
        }

        /// <summary>
        /// 与MoveRight不同，这里是指定向右移动到哪个位置（右边缘到哪个位置）。
        /// </summary>
        public override void MoveRightSiderTo(ModifingItem<Action, ModifingInfo> mi, double right)
        {
            if (mi == null || double.IsNaN(right) || masterEditor == null) return;

            double offset = 0;
            double maxRight = BottomRight.X;
            offset = maxRight - right;

            Point newStartPoint = new Point(startPoint.X - offset, startPoint.Y);
            Action actStart = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.StartPointTag,
                startPoint.ToString(), newStartPoint.ToString());
            this.StartPoint = newStartPoint;

            Point newCenterCPPoint = new Point(centerCPPoint.X - offset, centerCPPoint.Y);
            Action actCenterCP = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.CenterCPPointTag,
                centerCPPoint.ToString(), newCenterCPPoint.ToString());
            this.CenterCPPoint = newCenterCPPoint;

            Point newEndPoint = new Point(endPoint.X - offset, endPoint.Y);
            Action actEnd = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.EndPointTag,
                endPoint.ToString(), newEndPoint.ToString());
            this.EndPoint = newEndPoint;

            mi.AddAction(actStart);
            mi.AddAction(actCenterCP);
            mi.AddAction(actEnd);
        }

        /// <summary>
        /// 与MoveUp不同，这里是指定向上移动到哪个位置（上边缘到哪个位置）。
        /// </summary>
        public override void MoveTopSiderTo(ModifingItem<Action, ModifingInfo> mi, double top)
        {
            if (mi == null || double.IsNaN(top) || masterEditor == null) return;

            double offset = 0;
            double minTop = TopLeft.Y;
            offset = minTop - top;

            Point newStartPoint = new Point(startPoint.X, startPoint.Y - offset);
            Action actStart = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.StartPointTag,
                startPoint.ToString(), newStartPoint.ToString());
            this.StartPoint = newStartPoint;

            Point newCenterCPPoint = new Point(centerCPPoint.X, centerCPPoint.Y - offset);
            Action actCenterCP = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.CenterCPPointTag,
                centerCPPoint.ToString(), newCenterCPPoint.ToString());
            this.CenterCPPoint = newCenterCPPoint;

            Point newEndPoint = new Point(endPoint.X, endPoint.Y - offset);
            Action actEnd = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.EndPointTag,
                endPoint.ToString(), newEndPoint.ToString());
            this.EndPoint = newEndPoint;

            mi.AddAction(actStart);
            mi.AddAction(actCenterCP);
            mi.AddAction(actEnd);
        }

        public override void MoveWhenDraggingControler(Point newOutSidePoint)
        {
            //注释掉是因为需要支持“拖动控制点以更改挂接的目标部件”功能。当时未考虑这样会导致此功能失效。
            //if (IsLinked && masterEditor != null)
            //{
            //    ICanBeLinkedWidget icStart = masterEditor.GetWidget(startMasterId) as ICanBeLinkedWidget;
            //    ICanBeLinkedWidget icEnd = masterEditor.GetWidget(endMasterId) as ICanBeLinkedWidget;

            //    if (icStart != null && icEnd != null)
            //    {
            //        Rect startRect = icStart.OuterRect;
            //        Rect endRect = icEnd.OuterRect;
            //        DrawLine(startRect, endRect);
            //        return;
            //    }
            //}

            switch (draggingType)
            {
                case ControlDraggingType.Start:
                    {
                        Point newMovingPoint = newOutSidePoint;
                        DrawLine(newMovingPoint, this.centerCPPoint, this.endPoint);

                        //刷新文本块位置不放在这里，而是合并至DrawLine(Point,Point,Point)，因为需要一些坐标。
                        break;
                    }
                case ControlDraggingType.CenterCP:
                    {
                        Point newMovingPoint = newOutSidePoint;
                        DrawLine(this.startPoint, newMovingPoint, this.endPoint);

                        //刷新文本块位置不放在这里，而是合并至DrawLine(Point,Point,Point)，因为需要一些坐标。
                        break;
                    }
                case ControlDraggingType.End:
                    {
                        Point newMovingPoint = newOutSidePoint;
                        DrawLine(this.startPoint, this.centerCPPoint, newMovingPoint);

                        //刷新文本块位置不放在这里，而是合并至DrawLine(Point,Point,Point)，因为需要一些坐标。
                        break;
                    }
            }

            this.commentAdorner.Visibility =
                this.hyperLinkAdorner.Visibility = Visibility.Collapsed;
        }

        /// <summary>
        /// 移动挂接的主部件时，与此部件连接的线（就是本类的某个实例）需要自动相应地移动。
        /// </summary>
        /// <param name="tmpStartMasterRect">如果指定了此参数，则startRect应按此参数来移动。</param>
        /// <param name="tmpEndMasterRect">如果指定了此参数，则endRect应按此参数来移动。</param>
        public void MoveWhenDraggingMasterWidget(Rect? tmpStartMasterRect = null, Rect? tmpEndMasterRect = null)
        {
            ICanBeLinkedWidget startMaster = masterEditor.GetWidget(startMasterId) as ICanBeLinkedWidget;
            ICanBeLinkedWidget endMaster = masterEditor.GetWidget(endMasterId) as ICanBeLinkedWidget;
            if (startMaster == null || endMaster == null) return;

            Rect startRect = tmpStartMasterRect.HasValue ? tmpStartMasterRect.Value : startMaster.MovingRect;
            Rect endRect = tmpEndMasterRect.HasValue ? tmpEndMasterRect.Value : endMaster.MovingRect;

            DrawLine(startRect, endRect);

            this.startPresentateAdorner.Visibility =
                this.endPresentateAdorner.Visibility =
                this.commentAdorner.Visibility =
                this.hyperLinkAdorner.Visibility = Visibility.Collapsed;
        }

        public override void MoveWhenDraggingWidget(Point mousePoint)
        {
            if (masterEditor == null) return;

            Point newMovingPoint = mousePoint;
            Point globalLocation = masterEditor.MouseInfo.LeftButtonPreviewPoint;

            Point tmpStartPoint = new Point(startPoint.X - globalLocation.X + newMovingPoint.X,
                startPoint.Y - globalLocation.Y + newMovingPoint.Y);
            Point tmpEndPoint = new Point(endPoint.X - globalLocation.X + newMovingPoint.X,
                endPoint.Y - globalLocation.Y + newMovingPoint.Y);
            Point tmpCenterCPPoint = new Point(centerCPPoint.X - globalLocation.X + newMovingPoint.X,
                centerCPPoint.Y - globalLocation.Y + newMovingPoint.Y);

            DrawLine(tmpStartPoint, tmpCenterCPPoint, tmpEndPoint);

        }

        public override void RefreshArrows()
        {
            this.RefreshArrows(true);
        }

        /// <summary>
        /// 刷新箭头状态。
        /// </summary>
        /// <param name="drawLine">若为真，按已设置的startPoint/startCPpoint/endCPPoint/endPoint画线及箭头。</param>
        private void RefreshArrows(bool drawLine)
        {
            base.RefreshArrows();

            //if (drawLine) DrawLine();
        }

        /// <summary>
        /// 刷新所有控制点。
        /// </summary>
        public override void RefreshControlers()
        {
            #region 这些控制点的坐标由DrawLine()方法控制。因为不同的线型，控制点位置不同。
            //startCtrl.CenterPoint = this.startPoint;
            //endCtrl.CenterPoint = this.endPoint;

            //if (IsLinked == false)
            //{
            //    Point centerBasePoint;
            //    if (direction == Orientation.Horizontal)
            //    {
            //        centerBasePoint = new Point(startPoint.X + (endPoint.X - startPoint.X) / 2, this.centerCPPoint.Y);
            //    }
            //    else
            //    {
            //        centerBasePoint = new Point(this.centerCPPoint.X, startPoint.Y + (endPoint.Y - startPoint.Y) / 2);
            //    }

            //    centerCPCtrl.CenterPoint = centerBasePoint;
            //}
            //else
            //{
            //    centerCPCtrl.CenterPoint = this.centerCPPoint;
            //}
            #endregion

            if (isSelected)
            {
                //刷新控制点色彩
                if (masterEditor != null && masterEditor.MasterManager != null)
                {
                    if (startCtrl.MainSelectedBrush != masterEditor.MasterManager.WidgetStartControlerBrush)
                        startCtrl.MainSelectedBrush = masterEditor.MasterManager.WidgetStartControlerBrush;

                    if (centerCPCtrl.MainSelectedBrush != masterEditor.MasterManager.WidgetCenterControlerBrush)
                        centerCPCtrl.MainSelectedBrush = masterEditor.MasterManager.WidgetCenterControlerBrush;

                    if (endCtrl.MainSelectedBrush != masterEditor.MasterManager.WidgetEndControlerBrush)
                        endCtrl.MainSelectedBrush = masterEditor.MasterManager.WidgetEndControlerBrush;
                }

                startCtrl.Visibility =
                    endCtrl.Visibility = System.Windows.Visibility.Visible;

                if (IsLinked)
                {
                    centerCPCtrl.Visibility = System.Windows.Visibility.Hidden;
                }
                else
                {
                    centerCPCtrl.Visibility = System.Windows.Visibility.Visible;
                }
            }
            else
            {
                startCtrl.Visibility = centerCPCtrl.Visibility =
                    endCtrl.Visibility = System.Windows.Visibility.Hidden;
            }
        }

        public override void RefreshLineDash()
        {
            switch (lineDash)
            {
                case LineDashType.DashType.Dash:
                    {
                        this.mainPath.StrokeDashArray = LineDashType.dashCollection; break;
                    }
                case LineDashType.DashType.DashDotDot:
                    {
                        this.mainPath.StrokeDashArray = LineDashType.dashDotDotCollection; break;
                    }
                case LineDashType.DashType.Dot:
                    {
                        this.mainPath.StrokeDashArray = LineDashType.dotCollection; break;
                    }
                case LineDashType.DashType.Solid:
                    {
                        this.mainPath.StrokeDashArray = LineDashType.solidCollection; break;
                    }
                default:
                    {
                        this.mainPath.StrokeDashArray = LineDashType.dashDotCollection; break;
                    }
            }
        }

        public void RefreshLineForm()
        {
            this.DrawLine();
            this.RefreshIsTextVisible();

            if (this.mainTextPanel.Visibility == Visibility.Visible)
            {
                this.RefreshTextPanelLocatin();
            }
        }

        public override void RefreshIsSelected()
        {
            if (startMasterId != string.Empty)
            {
                startCtrl.Form = LineCtrlAdorner.ControlerType.Rectangle;
            }
            else
            {
                startCtrl.Form = LineCtrlAdorner.ControlerType.Ellipse;
            }

            if (endMasterId != string.Empty)
            {
                centerCPCtrl.Form =
                endCtrl.Form = LineCtrlAdorner.ControlerType.Rectangle;
            }
            else
            {
                centerCPCtrl.Form =
                endCtrl.Form = LineCtrlAdorner.ControlerType.Ellipse;
            }

            base.RefreshIsSelected();
        }

        /// <summary>
        /// 刷新线宽。
        /// </summary>
        public override void RefreshWidgetLineWidth()
        {
            //强制折线跳过宽度１（当作２看待）——因为会模糊，很难看。
            //mainPath.StrokeThickness = (lineWidth < 2 ? 2 : lineWidth);

            double newLineWidth = (widgetLineWidth < 1 ? 1 : widgetLineWidth);
            mainPath.StrokeThickness = newLineWidth;//还是支持宽度1的线为妙。

            if (widgetLineWidth == 1)
            {
                RenderOptions.SetEdgeMode(mainPath, EdgeMode.Aliased);
            }
            else
            {
                RenderOptions.SetEdgeMode(mainPath, EdgeMode.Unspecified);
            }

            startArrowPath.StrokeThickness = endArrowPath.StrokeThickness = newLineWidth;
        }

        public override void RefreshLocation()
        {
            base.RefreshLocation();

            // RefreshWidgetLineWidth(); // 会调用此方法。
            RefreshArrows();          // 重复了
            RefreshControlers();

            DrawLine();
            RefreshPresentateAdorners();
        }

        public void RefreshPresentateAdorners()
        {
            if (Globals.MainWindow.rtbtnAutoHidePolyLine.IsChecked == true && Globals.MainWindow.IsPresentatingByPath)
            {
                this.startPresentateAdorner.Visibility = this.endPresentateAdorner.Visibility = Visibility.Visible;
                this.startPresentateAdorner.InvalidateVisual();
                this.endPresentateAdorner.InvalidateVisual();
            }
            else
            {
                this.startPresentateAdorner.Visibility = this.endPresentateAdorner.Visibility = Visibility.Hidden;
            }
        }

        public override void RefreshPointWhenGroupIn(Point baseTopLeft)
        {
            Point oldStartPoint = startPoint;
            Point newStartPoint = new Point(oldStartPoint.X - baseTopLeft.X,
                oldStartPoint.Y - baseTopLeft.Y);
            StartPoint = newStartPoint;

            Point oldCenterCPPoint = centerCPPoint;
            Point newCenterCPPoint = new Point(oldCenterCPPoint.X - baseTopLeft.X,
                oldCenterCPPoint.Y - baseTopLeft.Y);
            CenterCPPoint = newCenterCPPoint;

            Point oldEndPoint = endPoint;
            Point newEndPoint = new Point(oldEndPoint.X - baseTopLeft.X,
                oldEndPoint.Y - baseTopLeft.Y);
            EndPoint = newEndPoint;
        }

        public override void RefreshPointWhenGroupOut(Point baseTopLeft)
        {
            Point oldStartPoint = startPoint;
            Point newStartPoint = new Point(oldStartPoint.X + baseTopLeft.X,
                oldStartPoint.Y + baseTopLeft.Y);
            StartPoint = newStartPoint;

            Point oldCenterCPPoint = centerCPPoint;
            Point newCenterCPPoint = new Point(oldCenterCPPoint.X + baseTopLeft.X,
                oldCenterCPPoint.Y + baseTopLeft.Y);
            CenterCPPoint = newCenterCPPoint;

            Point oldEndPoint = endPoint;
            Point newEndPoint = new Point(oldEndPoint.X + baseTopLeft.X,
                oldEndPoint.Y + baseTopLeft.Y);
            EndPoint = newEndPoint;
        }

        public override void RefreshWidgetLineColor()
        {
            if (Globals.MainWindow.rtbtnAutoHideBazeirLine.IsChecked == true && Globals.MainWindow.IsPresentatingByPath)
            {
                if (IsPresentating)
                {
                    this.startArrowPath.Fill =
                        this.startArrowPath.Stroke =
                        this.endArrowPath.Fill =
                        this.endArrowPath.Stroke =
                        this.mainPath.Stroke = Brushes.Transparent;
                }
                else
                {
                    this.startArrowPath.Fill =
                        this.startArrowPath.Stroke =
                        this.endArrowPath.Fill =
                        this.endArrowPath.Stroke =
                        this.mainPath.Stroke = this.widgetLineColor;
                }
            }
            else
            {

                startArrowPath.Stroke = endArrowPath.Stroke =
                    startArrowPath.Fill = endArrowPath.Fill =
                        mainPath.Stroke = WidgetLineColor;
            }
        }

        protected void RefreshSelectedStatus()
        {
            //base.RefreshSelectedStatus();
            RefreshControlers();
        }

        public override void RefreshIsShadowVisible()
        {
            base.RefreshIsShadowVisible();

            if (isShadowVisible)
            {
                this.mainPath.Effect = Widget.ShadowEffect;
            }
            else
            {
                this.mainPath.Effect = null;
            }
        }

        /// <summary>
        /// 仅在为PolyLine或CLine或LLine形态时有效。
        /// </summary>
        public override void RefreshTextPanelLocatin()
        {
            switch (this.LineForm)
            {
                case PolyLineForms.CLine:
                case PolyLineForms.LLine:
                case PolyLineForms.PolyLine:
                    {
                        Point startBasePoint = this.startBasePoint;
                        Point endBasePoint = this.endBasePoint;

                        RefreshTextPanelLocatin(ref startBasePoint, ref endBasePoint, ref centerBasePoint, this.direction);
                        break;
                    }
            }
        }

        private void RefreshTextPanelLocatin(ref Point startBasePoint, ref Point endBasePoint, ref Point centerBasePoint, Orientation direction)
        {
            LocateTextPanel(startBasePoint, endBasePoint, direction);
        }

        public override void RefreshIsTextVisible()
        {
            switch (this.lineForm)
            {
                case PolyLineForms.BigFishBone:
                case PolyLineForms.MediumFishBone:
                    {
                        this.mainTextPanel.Visibility = Visibility.Collapsed;
                        break;
                    }
                default:
                    {
                        base.RefreshIsTextVisible();
                        break;
                    }
            }
        }

        public void ResetControlers(ModifingItem<Action, ModifingInfo> mi)
        {
            if (mi == null || mi.ModifingInfo == null)
            {
                MessageBox.Show("　　PolyLineWidget的ResetControlers()方法的mi参数或mi.ModifingInfo参数不能为null。",
                    Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            if (masterEditor == null || masterEditor.MasterManager == null) return;

            mi.ModifingInfo.ModifingDescription = "复位控制点";

            Point newCenterCPPoint = new Point(startPoint.X + (endPoint.X - startPoint.X) / 2,
                startPoint.Y + (endPoint.Y - startPoint.Y) / 2);

            Action actCenterCPPoint = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.CenterCPPointTag,
                centerCPPoint.ToString(), newCenterCPPoint.ToString());

            CenterCPPoint = newCenterCPPoint;

            mi.AddAction(actCenterCPPoint);

            masterEditor.MasterManager.RegisterModifingItem(mi);
        }

        public override void UpdatePointsWhenPasting(Point basePasteTopLeft)
        {
            Point newStartPoint = new Point(startPoint.X + basePasteTopLeft.X,
               startPoint.Y + basePasteTopLeft.Y);

            StartPoint = newStartPoint;

            Point newCenterCPPoint = new Point(centerCPPoint.X + basePasteTopLeft.X,
                centerCPPoint.Y + basePasteTopLeft.Y);

            CenterCPPoint = newCenterCPPoint;

            Point newEndPoint = new Point(endPoint.X + basePasteTopLeft.X,
                endPoint.Y + basePasteTopLeft.Y);

            EndPoint = newEndPoint;
        }

        #endregion


        #region 其它=========================================================================================================

        //private enum ControlDraggingType { Start, End, None, CenterCP }
        //2012年5月30日已移植并合并至Enums.LineCtrlDraggingType文件中。

        private static DoubleCollection dashArray;

        #endregion
    }
}
